Taskwarrior
task warrior is the answer you've been looking for for task management.
It syncs between PCs (but is tolerant of connectivity issues), it can export
data to just about anything you could possibly want. CLI interface is simple,
and supports aliases for your most common workflow tasks. Has it's own builtin
calendar for displaying tasks. Tracks the time you spend performing tasks.
Because of taskwarrior's very accessible/flexible dataset, there are many front-ends to taskwarrior that facilitate one workflow or another. Some notable examples:
- taskwiki (define tasks/subtasks by indentation in vim)
- vit (ncurses interface to taskwarrior)
Install
Linux
task
sudo pacman -S task cower -s vit cd $HOME mkdir .task_pers .task_work ## create the taskdirsFreeBSD
taskd
## Note I am only installing the task-server on FreeBSD ## sudo pkg install taskd #### /etc/rc.conf taskd_enable="YES" #### ## (taskd does not come with an rc-script, but I wrote one) ## (and it lives in configsync repo ) useradd taskd chown taskd:taskd /usr/local/share/taskd su taskd sudo pw usermod will -G taskd ## add user 'will' to existing group 'taskd' # (you'll need to reboot for this to take effect)
Usage
CLI Structure
Task is the core command of taskwarrior. Each command is composed of 4 sections, all of which are entirely optional.
#task <filter> <command> <modifications> <miscellaneous> task +home list proj:test editor
Main Commands
task add <desc> ## new task task 1 del ## delete task entirely task log <desc> ## add task, and mark complete task 1 start ## start recording time on task task 1 stop ## stop recording time on task task 1 done ## mark task completePersonal Workflow
Taskwarrior is pretty flexible, but not quite flexible enough to suit my needs with a single task-server. Instead, I'll have separate task-servers for separate projects.
Commands
Task Server
/tmp/taskd.logdefault log-location for taskd /home/taskd/.taskdatapersonal location for taskdata dir
Task Client
Task Heirarchy
Without extensions, taskwarrior is built with each task as it's own independent unit, no centralized datastore is used to maintain a master collections of tasks, each task is self-contained.
These tasks are categorized into files based on their level of completion.
pending.datauncompleted tasks completed.dataall completed tasks backlog.data??? undo.datatotal undo history. (stores task old and new) ## example of a single task [description:"time in report timesheet" entry:"1457748143" modified:"1457800384" project:"dev.taskwarrior" status:"pending" uuid:"8c36f574-7165-4316-bb19-5ba6fde8a0dc"]
Tasks can then have metadata attached to them, which is used to categorize them, and makes it easier to search for them.
projects task add proj:dev "my task"subprojects task add proj:dev.subproj "my task"tags task add +mytag "my task"Task LifeCycle
task add <desc> ## add new tasks task ## list current tasks task 1 ## list info about task1 task 1 start ## start working on task1 task 1 done ## mark task 1 as complete task 1-3 done ## mark a range of tasks as done task 4 del ## delete a task task log <desc> ## log a task that you have already done. # you want to track everything.
Displaying Tasks
## Filters task entry.after:today-4days ## list all tasks entered in last 4x days task entry:yesterday ## list tasks entered yesterday task project:<project> ## list tasks associated with project ## Virtual Tags task 1 info ## get virtual-tags associated with task task +DUETODAY ## tasks due today task +DUE -DUETODAY ## tasks that are due _NOT_ today task +OVERDUE list ## tasks that are overdue task +WEEK list ## tasks due this week
Adding Task Metadata
## Adding Metadata task add project:<project> <desc> ## Create a task with metadata task 1 mod project:<project> ## modify existing task ## Types of MetaData ## Heirarchy task project:<project> <desc> ## Move a task to a different project task project:<project>.<subproject> <desc> task depends:2 <desc> ## task dependencies (task1 cannot be copleted until task2 finished) ## Dates task due:10th <desc> ## modify due date task scheduled:10th <desc> ## task is dormant until it's scheduled date # (then receives status 'ready') task wait:november <desc> ## hide task until nobember task until:december <desc> ## if you miss a deadline, task stays alive until december # when it deletes itself ## Filtering task priority:(H|L|M) <desc> ## priority high/low/medium task +problem -house <desc> ## Add/Remove Task Tags task status:pending <desc> ## moddify status of taskSearching
task /cat/ list ## list any tasks containing the word 'cat' task "/c[a-z]+/" list ## searches are regex by defaultReports/Graphs
## Most Used task summary ## overview of projects task timesheet ## short-term report of tasks finished task calendar ## displays a calendar of tasks/duedates ## All reorts task reports ## list of all available reports ## long-term graphs/reports task burndown.(daily|weekly|monthly) ## graph of daily started/pending/completed task ghistory.(monthly|annual) ## graph of history report task history.(monthly|annual) ## report of history
Config
~/.taskrcconfig file ~/.task/*task info storage ~/.taskdata/configtask-daemon config (points to --data location)
taskserver
https://taskwarrior.org/docs/taskserver/setup.htmlofficial taskserver docs
base configsu taskd ## Edit 'vars' file with your cert values ## mkdir ~/.taskdata #### /usr/local/share/taskd/vars CN = 192.168.1.211 #### /usr/local/share/taskd/generate ## documentation warns that this does not use sensible defaults. # need to configure manually (creates self-signed CA) ## create base config file ## taskd init --data /home/taskd/.taskdata ## create base-config taskd config server 192.168.1.211:53589 ## set addr/port to bind ## Generate certificates setenv TASKDDATA /home/taskd/.taskdata ## set root cp /usr/local/share/*.pem $TASKDDATA/ ## copy certs to TASKDATA dir ## make config use the certificates we just generated taskd config --force client.cert $TASKDDATA/client.cert.pem taskd config --force client.key $TASKDDATA/client.key.pem taskd config --force server.cert $TASKDDATA/server.cert.pem taskd config --force server.key $TASKDDATA/server.key.pem taskd config --force server.crl $TASKDDATA/server.crl.pem taskd config --force ca.cert $TASKDDATA/ca.cert.pem taskd config --force log $PWD/taskd.log taskd config --force pid.file $PWD/taskd.pid ## run taskd (make sure it works) ## taskd server
create usertaskd add org 'Personal' --data /home/taskd/.taskdata ## create organization 'Personal' taskd add user 'Personal' 'Will Pittman' --data /home/taskd/.taskdata ## add user 'Will Pittman' to organization 'Personal' ## Save the unique-key # f5cd9571-e723-11e5-a73d-001d09ab5523 cd /usr/local/share/taskd ./generate.client will_pittman.pem cp will* ~/.taskdata/ ## Copy Certificcates to your taskwarrior client. scp client* will@miranda:/home/will/.task/ ## copy client certificates to task-client scp ca.cert.pem will@miranda:/home/will/.task/ ## copy server's ca-cert to client
Routerforward port 53589 to taskwarrior locally.
task
add user from taskd
## Make sure you have the keys /home/will/.task/ca.cert.pem /home/will/.task/task.cert.pem /home/will/.task/task.key.pem ## configure task to use the taskd server task config taskd.server -- 192.168.1.211:53589 task config taskd.credentials -- Personal/Will Pittman/f5cd9571-e723-11e5-a73d-001d09ab5523 ## synchronize with the server task sync init
Custom Hooks
~/.task/hooks/*location of hooks. https://taskwarrior.org/docs/hooks_guide.html taskwarrior's excellent API/hook guide. Hook Types
on-addtask creation on-modifymodifying/annotating tasks (not on creation) on-launchonce the 'task' command has been initialized (run), but before it does anything. on-exitafter processing, but immediately before tasks are displayed onscreen Input/Output
Taskwarrior has a hook model that is inspired by git. TaskWarrior is built with events at key points. Hooks can subscribe to these events, and be run with specific information.
Hooks are subscribed to events based on their names
<event_name>-description
. The order of execution is alphabetical. Hooks can written in any language that can process CLI commands, and parse json. Hooks must have executable permissions.
WARNING:
Watch out! Different types of hooks provide a different number of lines, and expect different kinds of output. See https://taskwarrior.org/docs/hooks.html#interfaces
## see 'Interfaces' at the following link for more detailed ## information about input/output. https://taskwarrior.org/docs/hooks.html #### Input # the input sent to hook scripts consists of a single-line json object representing the # task. MUST BE A SINGLE LINE. { "description" : "test", "entry" : "20161105T202606Z", "modified" : "20161213T005507Z", "project" : "pers", "status" : "pending", "uuid" : "58fb9ddd-1ee4-4446-9e92-4f4be9d039e2" } #### Output # output consists of two lines: # - the single-line json object representing a task (presumably modified) # - a single line of text.Other than that, as a safeguard against silently corrupting your data, if json is not a task, or is malformed, it is ignored/discarded.
Example Script
The following is an example of a python script, used as a taskwarrior hook. All this script does is receive the JSON task sent to it, and spits it back out unmodified, with an exit code of 0 (not fail).
This is the base of all hook-scripts.
#!/usr/bin/env python import sys import json stdin = sys.stdin.readline() if stdin: task = json.loads(sys.stdin.readline()) task['desc'] = 'abcdefg' print(json.dumps(task)) print('updated task successfully') sys.exit(0)## Test-Run hook (outside of taskwarrior) chmod +x hook.py echo '{"name":"value"}' | ./hook.py >> {"name": "value"} ## Test that the hook exited correctly echo $? 0
Plugins/Hooks
https://github.com/kostajh/taskwarrior-time-tracking-hook taskwarrior time-tracking-hook (taskwarrior does not record total times spent on tasks by default, only what is accomplished.) https://github.com/blindFS/vim-taskwarrior allows you to toggle annotations on/off, switch out tags, etc. Looks more powerful than vit, the default taskwarrior interface. Time Tracking Hook
WARNING:
I no longer use the time-tracking hook, I have replaced it with the official timewarrior program.
sudo pip install taskwarrior-time-tracking-hook mkdir -p ~/.task/hooks ln -s /usr/bin/taskwarrior_time_tracking_hook $HOME/.task/hooks/on-modify.timetracking ## install the hook #### ~/.taskrc task config uda.totalactivetime.type duration task config uda.totalactivetime.label Total active time task config uda.totalactivetime.values '' ####