Logseq supports recurring tasks with three scheduling semantics, modeled on org-mode's three repeater cookies. Picking the right one lets you say exactly how the next occurrence should be computed when you mark a task DONE.
This document is the reference for contributors working on the
scheduler and for users who want the full behavior specification. The
short, user-facing version lives in
logseq/docs Tasks.md.
Repeats from the last time you marked the block done.
The next occurrence is one interval after the moment you marked the task DONE, regardless of what the original scheduled date was.
Best for: habits and cadence-driven recurrences — things where the clock restarts the moment you finish.
Example: A weekly task scheduled for 2026-04-01, completed on 2026-04-05, will next appear on 2026-04-12. If you'd forgotten and completed it on 2026-04-20, it would next appear on 2026-04-27. The interval is anchored to your completion, not to the calendar.
Keeps it on the same day of the week.
The next occurrence starts at original + one interval and keeps advancing in whole intervals until the result is strictly in the future. Because the arithmetic is in UTC and advances by whole weeks (or months, or years), weekly recurrences naturally land on the same day-of-week as the original.
Best for: calendar-anchored recurrences where completion is a side event and the anchor matters — "every Monday standup," "monthly review on the first of the month."
Example: A weekly standup scheduled for Monday, 2026-04-06:
- Completed Wednesday, 2026-04-08 → next occurrence Monday, 2026-04-13.
- Completed Friday, 2026-04-17 → next occurrence Monday, 2026-04-20.
This is the default when a recurring task has no explicit cookie.
Repeats in X y/m/w/d/h from when you originally scheduled it.
The next occurrence is exactly original + one interval. If completion was much later than the original date, the next occurrence may land in the past — which causes the task to appear overdue immediately. Org-mode calls this "stacking."
Best for: obligations tied to an exact calendar date that should not shift when you're late — monthly rent, annual renewals, fixed billing cycles.
Example: Rent due 2026-04-01, paid 2026-04-05 → next reminder 2026-05-01. Paid 2026-04-25 → next reminder still 2026-05-01.
A decision table for picking the right semantic:
| Intent | Cookie |
|---|---|
| "Every 7 days from when I last did it" | .+ |
| "Every Monday" | ++ |
| "The 1st of every month" | + |
Recurring tasks without an explicit repeat-type default to ++.
This preserves the behavior that existed before the three cookies were
honored independently; no existing task changes on upgrade. Users who
want .+ or + semantics can pick them via the repeat-setting
popover on the task.
The scheduler lives in src/main/frontend/worker/commands.cljs. It
dispatches on repeat-type via repeat-next-timestamp:
advance-from-completionimplements.+advance-from-scheduledimplements+advance-until-futureimplements++
The dispatch falls back to ++ for nil or unknown values, so the
scheduler is safe against missing or future-added cookie types.
Frequencies of zero or less short-circuit to nil before dispatch to
avoid infinite loops.
:logseq.property.repeat/repeat-type is a closed-values property
declared in deps/db/src/logseq/db/frontend/property.cljs. Its closed
values are:
:logseq.property.repeat/repeat-type.dotted-plus—.+:logseq.property.repeat/repeat-type.plus—+:logseq.property.repeat/repeat-type.double-plus—++(default)
The repeat-setting popover in
src/main/frontend/components/property/value.cljs exposes a "Next date"
selector bound to the repeat-type property. It appears whenever the
task's repeat checkbox is enabled.
Scheduler tests live in
src/test/frontend/worker/commands_test.cljs. Each of the three
semantics has a dedicated deftest; the preexisting
get-next-time-test exercises the default (++) path. Time is pinned
via with-redefs [t/now ...] for determinism.
- End-user docs: logseq/docs
Tasks.md - Org-mode spec: Repeated tasks
- Tracking issues: #7731, #11260, #6715, #8531