29.03.2023 at 10:57 am

Moving Away from Todoist - to Taskwarrior, SSH & Dropbox - Part 2

A syncing workflow with Taskwarrior, Dropbox and SSH + rsync.

This post continues from Part 1 - Why Todoist no longer works for me.

I write the following Taskwarrior workflow from a Linux point of view, and as someone comfortable with Vim and TUIs/terminal user interfaces. The same syncing setup should apply across all Unix-like systems. (In fact, my setup works on my Mac M1 machines with zero config changes.)


For syncing, I had 3 requirements:

  1. Tasks must sync automatically across all my local machines.

  2. Tasks must be accessible from a server, and sync from it too.

  3. The solution must use nothing beyond Dropbox and shell scripts.


  1. I installed Taskwarrior and its additional TUI on both my local and the server/remote machine.

    sudo apt-get install taskwarrior

    (The interesting part: locally I'm using TW 2.62. Whereas due to libc differences, I'm using an older version on my server: 2.53. But the task files are compatible, only that additional newer features are not accessible on the server, which I don't need most of the time.)

  2. Create and fill-up the local ~/.taskrc file:

  3. Create a similar remote ~/.taskrc file:

  4. Generate your local keys, and upload them to the server for passwordless logins with rsync:

    cat id_rsa.pub | ssh USER@SERVER 'cat >> .ssh/authorized_keys'
  5. For the syncing mechanism, I wrote a simple two-way/rsync-based mechanism - taskwarrior-sync-server.sh:

    echo "Syncing local machine with server..."
    rsync -auv ~/Dropbox/tasks USER@SERVER:~; 
    echo "Syncing server with local machine..."
    rsync -auv root@SERVER:/USER/tasks ~/Dropbox;
  6. With the above done, I then create taskwarrior_tui.sh. It encapsulates the syncing mechanism before/after calling Taskwarrior-TUI (and thus I no longer start the TUI directly):

    OS=$(uname -s)
    sh ~/_shell_scripts/taskwarrior-sync-server.sh
    if [ "$OS" = 'Darwin' ]; then
    sh ~/_shell_scripts/taskwarrior-sync-server.sh
  7. Lastly, set up and copy Bash aliases between local/remote. I've only a few for Taskwarrior:

    alias t="task"
    alias ta="task add"
    alias tan="task add +next"
    alias tard="task add +readings"
    alias ty="~/taskwarrior-sync-server.sh"
    alias tw="~/taskwarrior_tui.sh"

Benefits of This Approach

I think the above solution is simple and elegant! I believe so for these reasons:

  1. I'm glancing through tasks with Taskwarrior-TUI most of the time. Tasks sync between my remote/local machine whenever I load up/close the TUI, so I never need to manually sync anything, just like with Todoist.

  2. Yet when working from the standard Taskwarrior command-line interface (especially when batch-adding tasks) or when I want to, I can always sync tasks manually by calling taskwarrior-sync-server.sh directly.

  3. Syncing respects modification times. I've not encountered file conflicts.

  4. I can work on my tasks locally, or on the server when I only have my iPhone/iPad (e.g. with Termius/Blink). I can be anywhere with any of my machines, so long as I have SSH access.

  5. My tasks are always saved in a Dropbox folder. I need only sync to/from the server with one machine at a time; it is Dropbox that propagates the changes across all other machines. So I can now start, continue or end work from any machine, without need for another syncing script.

  6. Dropbox has automated version control. Its versioning history serves as backup, and with it, I can restore earlier copies without needing Git.

  7. Todoist's poor search means that tasks essentially disappear after I mark them complete. With Taskwarrior, I get proper archival, and even have access to the power of tools like ripgrep.

I particularly love this workflow. I've essentially emulated a task-syncing process across all my machines simpler than Taskserver, and without having to install further dependencies than what I already use. And it opens up whole other avenues of task execution (since I can pipe tasks to Python scripts and cronjobs). This workflow has never caused problems and I hope the experience continues.

Filed under:
Words: 600 words approx.
Time to read: 2.40 mins (at 250 wpm)
, , , , , , , , ,

Other suggested posts

  1. 18.10.2022 at 09:36 am / The Airplane Test of Fluency
  2. 20.05.2020 at 01:05 am / A Programmer & His Mechanical Friend
  3. 05.02.2020 at 10:26 pm / Nostalgic Raging Streets
  4. 31.12.2018 at 06:23 pm / Why Plain Text
  5. 30.12.2018 at 10:06 pm / Castles and Air
  6. 19.08.2018 at 02:13 pm / Saunter Not
  7. 03.12.2017 at 12:00 am / Declarative, Imperative, Functional Sandwiches
  8. 05.03.2016 at 12:00 am / Rather Be (Alexa Goddard's Version)
  9. 07.07.2014 at 12:00 am / If I Cannot Strengthen Our Bench
  10. 22.08.2010 at 12:00 am / 柿が赤くなると医者が青くなる
© Wan Zafran. See disclaimer.