Task Management and Time Tracking from the Command Line with Taskwarrior and Timewarrior

productivity

Taskwarrior is an OSS task management tool. It automatically calculates urgency from multiple factors like due dates and tags to determine priority. You can also execute scripts via hooks when tasks are added or completed.

$ brew install task

$ task add Write Taskwarrior article
Created task 1.

$ task add depends:1 Publish article
Created task 2.

$ task add recur:weekly due:monday Weekly review
Created task 3.

$ task list
ID Age D R Due        Description              Urg
 3 5s    R 2026-02-23 Weekly review            8.28
 1 5s                 Write Taskwarrior article   8
 2 5s  D              Publish article            -5

$ task 1 done
Completed task 1 'Write Taskwarrior article'.
Completed 1 task.
Unblocked task 2 'Publish article'.

$ task completed
ID UUID     Created    Completed  Age  P Project Tags                    R Due        Description
 - 87229646 2026-02-21 2026-02-21 2w                                                  Write Taskwarrior article

Tasks can have attributes like project, tag, due, and priority, which can be used for filtering.

$ task add project:home +shopping due:tomorrow +next priority:H Buy milk
Created task 1.

$ task add project:work Work task
Created task 2.

$ task project:home
ID Age P Project Tag           Due        Description Urg
 1 5s  H home    next shopping 2026-02-22 Buy milk    31.6

You can check the urgency breakdown with task info. For example, the due date coefficient is 12, and the score is calculated by multiplying it by the closeness to the deadline. +next is a special tag that adds 15 to urgency.

$ task 3 info
Name          Value
ID            3
Description   Today's tasks
Status        Pending
Entered       2026-02-21 16:36:07 (1min)
Due           2026-02-21 00:00:00
Last modified 2026-02-21 16:36:07 (1min)
Virtual tags  DUE DUETODAY LATEST MONTH OVERDUE PENDING QUARTER READY TODAY UNBLOCKED WEEK YEAR
UUID          61da91f0-ec64-4ec3-b86e-85a44f7b1fd9
Urgency       9.117

    due   0.76 *   12 =   9.12
                        ------
                         9.117

By placing scripts in ~/.task/hooks, you can execute them when tasks are added or modified.

$ cat ~/.task/hooks/on-add-sample
#!/bin/bash
read input
echo "$input"
echo "Task has been added"
exit 0

$ chmod +x ~/.task/hooks/on-add-sample

$ task add Test
Created task 4.
Task has been added

There are many related tools from official and third-party sources. The official Timewarrior can record time spent on tasks. It also has a calendar view like Toggl. By placing on-modify.timewarrior in ~/.task/hooks/, tracking automatically starts with task start. While Taskwarrior allows multiple tasks to be started simultaneously, Timewarrior only tracks one at a time, so starting a new task automatically stops the previous tracking.

$ cp "$(brew --prefix timewarrior)/share/doc/timew/ext/on-modify.timewarrior" ~/.task/hooks/
$ chmod +x ~/.task/hooks/on-modify.timewarrior

$ task 1 start
Tracking Task name
  Started 2026-02-21T17:14:42

$ task 1 done
Recorded Task name
  Started 2026-02-21T17:14:42
  Ended              17:14:45
  Total               0:00:03

$ timew summary
Wk Date       Day ID Tags      Start    End      Time
-- ---------- --- -- --------- -------- -------- -------
W8 2026-02-21 Sat @1 Task name 17:14:42 17:14:45 0:00:03

The official taskchampion-sync-server enables syncing tasks across multiple devices. Each client has its own client_id, and data is end-to-end encrypted with a shared encryption_secret.

$ docker run -d -p 8080:8080 ghcr.io/gothenburgbitfactory/taskchampion-sync-server

$ task config sync.server.url http://localhost:8080
$ task config sync.server.client_id $(uuidgen)
$ task config sync.encryption_secret <secret>

$ task sync
Syncing with sync server at http://localhost:8080
Success!
Sent 45 local operations to the server

The third-party VIT is an interactive TUI client. Use a to add, d to complete, m to modify, b to start/stop, f to change filters, and / to search text. Switch between views like list and completed using :list, :completed, etc. Since it doesn’t auto-refresh, use Ctrl+l to manually refresh.