+To remove the annotation, pass its description to ``remove_annotation()`` method::
+
+ >>> task.remove_annotation("we can annotate saved tasks")
+
+Alternatively, you can pass the ``TaskAnnotation`` object itself::
+
+ >>> task.remove_annotation(task['annotations'][0])
+
+
+Running custom commands
+-----------------------
+
+To run a custom commands, use ``execute_command()`` method of ``TaskWarrior`` object::
+
+ >>> tw = TaskWarrior()
+ >>> tw.execute_command(['log', 'Finish high school.'])
+ [u'Logged task.']
+
+You can use ``config_override`` keyword argument to specify a dictionary of configuration overrides::
+
+ >>> tw.execute_command(['3', 'done'], config_override={'gc': 'off'}) # Will mark 3 as completed and it will retain its ID
+
+Setting custom configuration values
+-----------------------------------
+
+By default, TaskWarrior does not use any of configuration values stored in
+your .taskrc. To see what configuration values are passed to each executed
+task command, have a peek into ``config`` attribute of ``TaskWarrior`` object::
+
+ >>> tw.config
+ {'confirmation': 'no', 'data.location': '/home/tbabej/.task'}
+
+To pass your own configuration, you just need to update this dictionary::
+
+ >>> tw.config.update({'hooks': 'off'}) # tasklib will not trigger hooks
+
+Creating hook scripts
+---------------------
+
+From version 2.4.0, TaskWarrior has support for hook scripts. Tasklib provides
+some very useful helpers to write those. With tasklib, writing these becomes
+a breeze::
+
+ #!/usr/bin/python
+
+ from tasklib.task import Task
+ task = Task.from_input()
+ # ... <custom logic>
+ print task.export_data()
+
+For example, plugin which would assign the priority "H" to any task containing
+three exclamation marks in the description, would go like this::
+
+ #!/usr/bin/python
+
+ from tasklib.task import Task
+ task = Task.from_input()
+
+ if "!!!" in task['description']:
+ task['priority'] = "H"
+
+ print task.export_data()
+
+Tasklib can automatically detect whether it's running in the ``on-modify`` event,
+which provides more input than ``on-add`` event and reads the data accordingly.
+
+This means the example above works both for ``on-add`` and ``on-modify`` events!
+
+Consenquently, you can create just one hook file for both ``on-add`` and
+``on-modify`` events, and you just need to create a symlink for the other one.
+This removes the need for maintaining two copies of the same code base and/or
+boilerplate code.
+
+
+Working with UDAs
+-----------------
+
+Since TaskWarrior does not read your .taskrc, you need to define any UDAs
+in the TaskWarrior's config dictionary, as described above.
+
+Let us demonstrate this on the same example as in the TaskWarrior's docs::
+
+ >>> tw = TaskWarrior()
+ >>> tw.config.update({'uda.estimate.type': 'numeric'})
+
+Now we can filter and create tasks using the estimate UDA::
+
+ >>> task = Task(tw, description="Long task", estimate=1000)
+ >>> task.save()
+ >>> task['id']
+ 1
+
+This is saved as UDA in the TaskWarrior::
+
+ $ task 1 export
+ {"id":1,"description":"Long task","estimate":1000, ...}
+
+As long as ``TaskWarrior``'s config is updated, we can approach UDAs as built in attributes::
+
+ >>> tw.tasks.filter(estimate=1000)
+ Long task
+
+Syncing
+-------
+
+Syncing is not directly supported by tasklib, but it can be made to work in a similiar way
+as the UDAs. First we need to update the ``config`` dictionary by the values required for
+sync to work, and then we can run the sync command using the ``execute_command()`` method::
+
+ >>> tw = TaskWarrior()
+ >>> sync_config = {
+ ... 'taskd.certificate': '/home/tbabej/.task/tbabej.cert.pem',
+ ... 'taskd.credentials': 'Public/tbabej/34af54de-3cb2-4d3d-82be-33ddb8fd3e66',
+ ... 'taskd.server': 'task.server.com:53589',
+ ... 'taskd.ca': '/home/tbabej/.task/ca.cert.pem',
+ ... 'taskd.trust': 'ignore hostname'}
+ >>> tw.config.update(sync_config)
+ >>> tw.execute_command(['sync'])