Showcase: bidirectional Google Tasks ↔ Microsoft To Do sync with Apps Script

I built tasks-todo-sync, a small MIT-licensed, self-hosted Google Apps Script bridge for people who use both Google Tasks and Microsoft To Do.

It uses scheduled state comparison rather than event chaining: map task identities and fields, compare the latest known state, then create, update, or complete items on either side. This keeps the sync understandable when edits arrive out of order or one API is temporarily unavailable.

Apps Script keeps deployment lightweight, while logs make API failures inspectable. The trade-offs are real: quotas, token expiry, renamed/deleted lists, transient failures, provider-specific fields, and conflict edge cases. Test with a small task set and back up important data first.

Repo and setup notes: GitHub - simonchai-tw/tasks-todo-sync: Self-hosted, bidirectional sync between Google Tasks and Microsoft To Do, powered by Google Apps Script. · GitHub

I’d especially welcome feedback from Apps Script developers on conflict handling and quota-friendly scheduling.

I’m developing something similar that uses the same functionalities. Thank you for sharing your product, I will attempt to provide the best feedback possible for you.

Best,
Jacob

Thanks, Jacob — I really appreciate it. It’s especially nice to hear from someone working on something in the same space, and I’d be very interested in any feedback or ideas you come across.

There’s quite a bit more planned for the project as well, including better subtask/checklist support, safer field-level conflict handling, recurrence experiments, and continued work on reliability and recovery around the less friendly API edge cases.

The idea behind the project is fairly simple: not quite world peace, unfortunately, but hopefully removing one of those small bits of friction from everyday life for people who happen to live in both the Google and Microsoft ecosystems. Since it’s open source, I’d like whatever work goes into solving these problems to be useful to more than just me.

If you get a chance, please take a look at the GitHub repo, try it out, and give it a star if you think it’s useful. Feel free to follow the project as well — more features will be rolling out over time.

And of course, if you find anything questionable, broken, or simply have a better idea, comments here or issues/discussions on GitHub are always welcome. I’m all ears.

Thanks again!

Update: v1.0.0 is out — first stable release.

Since this post, the project has grown a lot:

  • Windows one-click installer (Tasks-ToDo-Sync-Setup.exe). Download, run, follow the wizard — no terminal, no npx.
  • 549/549 tests passing, plus a five-axis adversarial review of the engine: state machines, fuzzing, concurrency, mutation testing, static consistency.
  • Fail-closed throughout: ambiguous creates don’t guess, deletions take two rounds with live revalidation, state has checksums with previous-generation restore.
  • Time Bridge: [TTS-TIME:HH:mm] markers in Google Tasks notes become the canonical time record, rendered to Microsoft reminders + optional Calendar projection.

Honest limits, unchanged: ~300 task pairs recommended (600 is the tested stress limit, not a promise), personal Microsoft accounts for the easy path, 10-minute sync cadence.

MIT, self-hosted in your own Apps Script project. Repo: GitHub - simonchai-tw/tasks-todo-sync: Direct two-way sync between Google Tasks & Microsoft To Do in one seamless loop. Private & self-hosted. · GitHub

This is a lovely piece of work, and scheduled state comparison is the wiser choice over event chaining for exactly the reasons you mention. Out-of-order edits and transient API failures are where naive sync breaks. The honest notes about quotas and conflict edge cases are refreshing too. The Google and Microsoft ecosystem overlap is a real nuisance, so a small bridge like this has genuine value. Following with interest.

Thanks — glad the design notes landed. On capacity: the binding limit isn’t a task count, it’s bytes. Sync state lives in Apps Script User Properties, gzip+Base64 encoded and chunked (7,000 chars, up to 100 chunks per generation). The preflight envelope is 450 KiB aggregate with an 8 KiB per-property cap, plus a 2 MiB uncompressed ceiling. We stress-tested to 600 task pairs; typical users sit well under that. At 360 KiB (80% of the safe envelope) the engine emails a storage-pressure alert, at most once per 30 days, so you get warned before it fails closed.

Longer term, one possible direction is to pair this with the cross-cloud attachment vault on the roadmap (saving To Do attachments to Google Drive and linking them in Google Tasks): older sync state could move to Drive as cold storage alongside it, keeping only the hot set in Properties. The hard part isn’t the move itself — it’s the hot/cold boundary: what gets evicted, when it gets rehydrated, and how that stays consistent with the checksummed generations. That part still needs real design work, so I’m not putting a date on it.