CalDAV Task Sync

pending

by speze88

Bidirectionally synchronize markdown tasks tagged with #caldav to/from a CalDAV server.

Updated 24d agoMITDiscovered via Obsidian Unofficial Plugins
View on GitHub

Obsidian CalDAV Task Sync

An Obsidian plugin that bidirectionally synchronizes markdown tasks to/from a CalDAV server (e.g. mailcow/SOGo).

Features

  • Tag tasks with a configured calendar tag such as #caldav, #work, or #private
  • Map multiple CalDAV calendars to different tags
  • Syncs on file save — no background polling
  • Bidirectional: push completions to the server, pull remote title/status changes back
  • UIDs stored in invisible HTML comments so your notes stay readable
  • Works with any CalDAV server that supports VTODO (mailcow, SOGo, Nextcloud, Baikal, etc.)

Task Format

Before sync (you write this):

- [ ] Buy groceries #private

After sync (UID written back automatically):

- [ ] Buy groceries #private <!-- caldav-uid:550e8400-e29b-41d4-a716-446655440000 -->

The UID comment is invisible in Obsidian's reading/preview mode.

Installation

Manual

  1. Download or build main.js and manifest.json
  2. Create the plugin folder in your vault:
    <vault>/.obsidian/plugins/obsidian-caldav-sync/
    
  3. Copy main.js and manifest.json into that folder
  4. Enable the plugin in Obsidian → Settings → Community plugins

Build from source

git clone https://github.com/your-username/obsidian-caldav-sync
cd obsidian-caldav-sync
npm install
npm run build

Then copy main.js and manifest.json to your vault's plugin folder as above.

Configuration

Go to Settings → CalDAV Task Sync and add one or more calendar mappings:

FieldDescriptionExample
Calendar nameOptional label shown in settingsPrivate
Server URLFull CalDAV calendar URL with trailing slashhttps://mail.example.com/SOGo/dav/user@example.com/Calendar/personal/
UsernameUsername for this calendar (usually your full email for mailcow)user@example.com
PasswordPassword for this calendar
TagTag that routes a task into this calendar#private

Use Add calendar to create additional mappings. Each calendar stores its own URL and credentials, so different servers or accounts can be used side by side.

Example mappings:

TagCalendar
#privatePersonal CalDAV calendar
#workWork CalDAV calendar

Example task routing:

- [ ] Pay rent #private
- [ ] Prepare Q2 review #work

Each task is synced to the calendar whose configured tag appears on the same task line.

Finding your CalDAV URL (mailcow / SOGo)

Your calendar URL typically follows this pattern:

https://<mail-server>/SOGo/dav/<email>/Calendar/<calendar-name>/

You can verify it with curl:

curl -u user@example.com:password \
  https://mail.example.com/SOGo/dav/user@example.com/Calendar/personal/ \
  -X PROPFIND -H "Depth: 0"

A 207 Multi-Status response confirms the URL and credentials are correct.

Sync Behavior

Sync is triggered every time you save a markdown file.

Conflict resolution

ScenarioResult
Local [x], remote incompleteLocal wins — pushes STATUS:COMPLETED
Local [ ], remote completedRemote wins — marks task [x] in your note
Local title differs from remote SUMMARYRemote wins — updates the title in your note
Remote VTODO not found (404)Warning logged, local task unchanged
ETag conflict (412)Re-fetches ETag and retries the PUT once

Re-entrancy

When the plugin writes UIDs or pulled changes back to a file, it uses an internal guard to prevent that write from triggering another sync loop.

Dependencies

  • tsdav — CalDAV client
  • uuid — UID generation

Limitations

  • No periodic background sync — changes only sync on file save
  • Remote-only tasks (created outside Obsidian) are not pulled into notes automatically
  • No support for recurring tasks, due dates, or priorities (v1)
  • Sync tag must appear on the same line as the task checkbox

License

MIT

For plugin developers

Search results and similarity scores are powered by semantic analysis of your plugin's README. If your plugin isn't appearing for searches you'd expect, try updating your README to clearly describe your plugin's purpose, features, and use cases.