Obsidian Task Rollover
Bullet-journal–style end-of-day task migration. Unfinished tasks (- [ ]) from
today's note get copied forward to the next workday, and marked as migrated in
today's note.
Configuration
VAULT_DAILY: absolute path to the daily notes folder (e.g./Users/you/obsidian/vault/Lead/Daily)
If not specified, infer from context or ask.
Step 1: Identify source note
Default source = today's note. If the user specifies a date ("roll over Monday's tasks"), resolve that date instead.
SOURCE_DATE=$(date +%Y-%m-%d)
SOURCE="${VAULT_DAILY}/${SOURCE_DATE}.md"
If the source note doesn't exist, report and stop: nothing to migrate.
Step 2: Find next workday
TARGET_DATE=$(python3 -c "
from datetime import date, timedelta
d = date.fromisoformat('${SOURCE_DATE}') + timedelta(days=1)
while d.weekday() >= 5: # 5=Sat, 6=Sun
d += timedelta(days=1)
print(d)
")
TARGET="${VAULT_DAILY}/${TARGET_DATE}.md"
Skips weekends. If today is Friday, tasks roll to Monday.
Step 3: Extract incomplete tasks
Read the source note and collect all lines matching - [ ] that are:
- Not inside the
## PRs to reviewsection (that section is auto-managed by theobsidian-pr-syncskill: don't touch it) - Not already migrated (
- [>]lines: idempotency guard)
Sections to skip entirely: ## PRs to review. Stop collecting at the nav footer
(*← [[...).
Collect both the task lines and which section (h2 heading) they belong to, so the target note can group them the same way.
Step 4: Mark tasks as migrated in source note
For each collected task line in the source note, replace:
- [ ] some task
with:
- [>] some task → [[Lead/Daily/TARGET_DATE|TARGET_DATE]]
The [>] is the bullet journal migration arrow: "moved forward". The link lets you
jump to where the task landed.
Do not replace tasks that are already checked (- [x]) or already migrated
(- [>). Only unticked - [ ] tasks.
Step 5: Write to target note
If the target note exists
Check whether a ## Carried over section already exists:
- If yes: replace its content (idempotent: re-running a migration is safe)
- If no: insert it before the nav footer line (
*← [[...) or at end of file
If the target note doesn't exist
Create it using the standard daily note template:
---
type: daily
date: TARGET_DATE
tags: [lead/daily]
---
# WEEKDAY, D MMM YYYY
## Top 3 for today
1.
2.
3.
## People check-in
> Who needs something from me today?
- [[]]
## Notes / journal
## Open loops
> Things I started but didn't finish
-
## Actions
- [ ]
---
*← [[Lead/Daily/SOURCE_DATE|Yesterday]] | [[Lead/Daily/NEXT_NEXT_DATE|Tomorrow]] →*
Then append the ## Carried over section.
Carried over section format
## Carried over
> Migrated from [[Lead/Daily/SOURCE_DATE|SOURCE_DATE]]
### SECTION_NAME (if tasks came from a named section)
- [ ] task text ↩ [[Lead/Daily/SOURCE_DATE|SOURCE_DATE]]
### Actions (if tasks came from ## Actions)
- [ ] another task ↩ [[Lead/Daily/SOURCE_DATE|SOURCE_DATE]]
Rules:
- Group tasks by the section they came from in the source note
- If all tasks are from
## Actions, omit the subsection header (keep it flat) - The
↩link back to the source date lets you trace where the task originated
Step 6: Report
Rolled over N tasks from SOURCE_DATE → TARGET_DATE
From ## Actions: X tasks
From ## Open loops: Y tasks
Marked [>] in: Lead/Daily/SOURCE_DATE.md
Written to: Lead/Daily/TARGET_DATE.md
If there are zero incomplete tasks, report:
No incomplete tasks in SOURCE_DATE, nothing to roll over ✓
Invocation patterns
Manual:
- "roll over today's tasks to tomorrow"
- "migrate my open tasks, it's end of day"
- "carry forward unfinished items from today"
Scheduled (end-of-day or start-of-morning): Runs silently. Picks up today's note automatically.
In a remote CCR agent: Clone the vault repo, run the rollover, commit and push. The local Obsidian Git plugin pulls the changes automatically.
Edge cases
- Tasks with sub-bullets: Copy the full block (task + its indented children)
- Duplicate migration: Re-running replaces the
## Carried oversection. It never duplicates. Tasks already marked[>]in source are not re-processed. - Friday → Monday: The weekend-skip logic handles this. The Monday note is created if it doesn't exist.
- Task already in target: No dedup check. If you manually added the same task to tomorrow and then run migration, it'll appear twice. Acceptable: easy to clean up.