TaskWarrior¶
The main class for interacting with TaskWarrior.
TaskWarrior(task_cmd=None, taskrc_file=None, data_location=None, adapter=None)
¶
A Python API wrapper for TaskWarrior.
By default uses :class:~taskwarrior.adapters.taskchampion_adapter.TaskChampionAdapter
for direct SQLite access — no task binary required. Pass
task_cmd="task" (or any path to the binary) to use the classic CLI
adapter instead.
Both adapters read configuration lazily from
:attr:config_store, so changes made via
tw.config_store.set_value(…) are immediately effective on the next
adapter call — no adapter recreation required.
.. note::
Changing data_location at runtime is not supported; create a new
:class:TaskWarrior instance in that case.
Attributes:
| Name | Type | Description |
|---|---|---|
config_store |
Live view of the taskrc configuration. Use
:meth: |
|
adapter |
AdapterProtocol
|
The underlying adapter instance (TaskChampion or CLI). |
context_service |
AdapterProtocol
|
Service for managing contexts. |
uda_service |
AdapterProtocol
|
Service for managing UDAs. |
Example
Basic usage (no binary needed)::
from taskwarrior import TaskWarrior, TaskInputDTO
tw = TaskWarrior()
task = TaskInputDTO(description="Buy groceries")
added = tw.add_task(task)
print(f"Added task: {added.uuid}")
Live configuration update (sync config, UDA, context, …)::
tw = TaskWarrior()
tw.config_store.set_value("sync.server.origin", "https://sync.example.com")
tw.config_store.set_value("sync.encryption.secret", "my-passphrase")
tw.synchronize() # uses the new config immediately
Explicit CLI adapter::
tw = TaskWarrior(task_cmd="task")
Custom paths::
tw = TaskWarrior(
taskrc_file="/path/to/.taskrc",
data_location="/path/to/data",
)
Initialize the TaskWarrior wrapper.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
task_cmd
|
str | None
|
Path or name of the TaskWarrior binary. When |
None
|
taskrc_file
|
str | None
|
Path to the taskrc configuration file. If None, uses the TASKRC environment variable or defaults to ~/.taskrc. |
None
|
data_location
|
str | None
|
Path to the TaskWarrior data directory. If None,
uses the TASKDATA environment variable, the value from taskrc,
or |
None
|
adapter
|
AdapterProtocol | None
|
Explicit adapter instance. Overrides task_cmd for CRUD
operations. Useful for injecting a custom or in-memory adapter
(e.g. |
None
|
add_task(task)
¶
Add a new task to TaskWarrior.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
task
|
TaskInputDTO
|
The task data to create. |
required |
Returns:
| Type | Description |
|---|---|
TaskOutputDTO
|
The created task with UUID and other fields populated. |
Raises:
| Type | Description |
|---|---|
TaskValidationError
|
If the task data is invalid or creation fails. |
Example
task = TaskInputDTO(description="Call mom", tags=["family"]) added = tw.add_task(task) print(added.uuid)
modify_task(task, task_id)
¶
Modify an existing task.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
task
|
TaskInputDTO
|
The new task data to apply. |
required |
task_id
|
TaskRef
|
The task ID (integer) or UUID to modify. |
required |
Returns:
| Type | Description |
|---|---|
TaskOutputDTO
|
The updated task. |
Raises:
| Type | Description |
|---|---|
TaskNotFound
|
If the task doesn't exist. |
TaskValidationError
|
If the modification fails. |
Example
task = TaskInputDTO(description="Updated description") updated = tw.modify_task(task, "abc-123-uuid")
get_task(task_id)
¶
Retrieve a single task by ID or UUID.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
task_id
|
TaskRef
|
The task ID (integer) or UUID to retrieve. |
required |
Returns:
| Type | Description |
|---|---|
TaskOutputDTO
|
The requested task. |
Raises:
| Type | Description |
|---|---|
TaskNotFound
|
If the task doesn't exist. |
Example
task = tw.get_task(1) # By ID task = tw.get_task("abc-123-uuid") # By UUID task = tw.get_task(TaskID(1)) # Using TaskID
get_tasks(filter='', include_completed=False, include_deleted=False, apply_context=True)
¶
Retrieve multiple tasks matching a filter.
The filter expression is automatically wrapped in parentheses so
compound expressions (e.g. "project:a or project:b") work
correctly without needing manual parentheses.
Deleted and completed tasks are excluded by default; use include_completed / include_deleted to override.
If a context is active and apply_context is True (the default),
its read_filter is applied in addition to the provided filter
(combined with AND). Pass apply_context=False to bypass context
injection and query raw tasks regardless of the active context.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
filter
|
str
|
TaskWarrior filter expression. Examples:: tw.get_tasks() # pending only tw.get_tasks("project:work +urgent") # project filter tw.get_tasks("project:dmc or project:pro") # OR — works! tw.get_tasks("project:work", include_completed=True) tw.get_tasks(apply_context=False) # bypass context |
''
|
include_completed
|
bool
|
Include completed tasks (default |
False
|
include_deleted
|
bool
|
Include deleted tasks (default |
False
|
apply_context
|
bool
|
When |
True
|
Returns:
| Type | Description |
|---|---|
list[TaskOutputDTO]
|
List of tasks matching the filter. |
Raises:
| Type | Description |
|---|---|
TaskWarriorError
|
If the query fails. |
get_recurring_task(task_id)
¶
Get the parent recurring task template.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
task_id
|
TaskRef
|
The UUID of a recurring task or one of its instances. |
required |
Returns:
| Type | Description |
|---|---|
TaskOutputDTO
|
The parent recurring task template. |
Raises:
| Type | Description |
|---|---|
TaskNotFound
|
If the task doesn't exist. |
get_recurring_instances(task_id)
¶
Get all instances of a recurring task.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
task_id
|
TaskRef
|
The UUID of the parent recurring task. |
required |
Returns:
| Type | Description |
|---|---|
list[TaskOutputDTO]
|
List of task instances created from the recurring template. |
Raises:
| Type | Description |
|---|---|
TaskNotFound
|
If the parent task doesn't exist. |
delete_task(task_id)
¶
Mark a task as deleted.
The task is not permanently removed; use purge_task for that.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
task_id
|
TaskRef
|
The task ID or UUID to delete. |
required |
Raises:
| Type | Description |
|---|---|
TaskOperationError
|
If the operation fails (e.g., task already deleted). |
purge_task(task_id)
¶
Permanently remove a task from the database.
Unlike delete_task, this cannot be undone.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
task_id
|
TaskRef
|
The task ID or UUID to purge. |
required |
Raises:
| Type | Description |
|---|---|
TaskOperationError
|
If the operation fails (e.g., task was not deleted first). |
done_task(task_id)
¶
Mark a task as completed.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
task_id
|
TaskRef
|
The task ID or UUID to complete. |
required |
Raises:
| Type | Description |
|---|---|
TaskOperationError
|
If the operation fails (e.g., task is already completed). |
Example
tw.done_task(1) tw.done_task("abc-123-uuid") tw.done_task(TaskID(1))
start_task(task_id)
¶
Start working on a task.
Sets the task's start time to now, indicating active work.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
task_id
|
TaskRef
|
The task ID or UUID to start. |
required |
Raises:
| Type | Description |
|---|---|
TaskOperationError
|
If the operation fails (e.g., task is already started). |
stop_task(task_id)
¶
Stop working on a task.
Clears the task's start time.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
task_id
|
TaskRef
|
The task ID or UUID to stop. |
required |
Raises:
| Type | Description |
|---|---|
TaskOperationError
|
If the operation fails (e.g., task was not started). |
annotate_task(task_id, annotation)
¶
Add an annotation (note) to a task.
Annotations are timestamped notes attached to tasks.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
task_id
|
TaskRef
|
The task ID or UUID to annotate. |
required |
annotation
|
str
|
The annotation text to add. |
required |
Raises:
| Type | Description |
|---|---|
TaskOperationError
|
If the operation fails (e.g., task not found). |
Example
tw.annotate_task(1, "Discussed with team, need more info")
define_context(context)
¶
Define a new context from a ContextDTO.
The context argument must be a ContextDTO instance containing name, read_filter and write_filter.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
context
|
ContextDTO
|
ContextDTO instance with the context definition. |
required |
Raises:
| Type | Description |
|---|---|
TaskWarriorError
|
If context creation fails. |
apply_context(context)
¶
Activate a context.
Once applied, all task queries will be filtered by this context.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
context
|
str
|
Name of the context to apply. |
required |
Raises:
| Type | Description |
|---|---|
TaskWarriorError
|
If the context doesn't exist or application fails. |
Example
tw.apply_context("work")
unset_context()
¶
Deactivate the current context.
Returns to showing all tasks without context filtering.
Raises:
| Type | Description |
|---|---|
TaskWarriorError
|
If unsetting fails. |
get_contexts()
¶
List all defined contexts.
Returns:
| Type | Description |
|---|---|
list[ContextDTO]
|
List of context definitions with names and filters. |
Raises:
| Type | Description |
|---|---|
TaskWarriorError
|
If retrieval fails. |
get_current_context()
¶
Get the name of the currently active context.
Returns:
| Type | Description |
|---|---|
str | None
|
The context name, or None if no context is active. |
Raises:
| Type | Description |
|---|---|
TaskWarriorError
|
If retrieval fails. |
delete_context(context)
¶
Delete a defined context.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
context
|
str
|
Name of the context to delete. |
required |
Raises:
| Type | Description |
|---|---|
TaskWarriorError
|
If the context doesn't exist or deletion fails. |
has_context(context)
¶
Check if a context exists.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
context
|
str
|
Name of the context to check. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if the context exists, False otherwise. |
is_sync_configured()
¶
Return True if synchronization is configured for this TaskWarrior instance.
has_local_changes()
¶
Return True if there are local changes not yet pushed to the sync server.
For the :class:~taskwarrior.adapters.taskchampion_adapter.TaskChampionAdapter
this queries the real pending-operations count from the SQLite replica.
For the CLI adapter this always returns False (the CLI manages sync
state internally).
.. note::
This only reflects the local side. New tasks or changes on the
remote server cannot be detected without calling :meth:synchronize.
Example
tw = TaskWarrior() tw.add_task(TaskInputDTO(description="Buy milk")) tw.has_local_changes() # True — not yet synced tw.synchronize() tw.has_local_changes() # False — fully synced
pending_local_ops_count()
¶
Return the number of local operations pending synchronization.
Useful for logging or progress display. 0 means the local replica
is fully synced (from the local side).
Returns 0 for the CLI adapter.
synchronize()
¶
Run TaskWarrior synchronization via task sync.
Delegates to the TaskWarrior CLI's built-in sync command. Synchronization settings (server address, credentials, or local path) must be configured in the taskrc file before calling this method.
Raises:
| Type | Description |
|---|---|
TaskSyncError
|
If no sync backend is configured or synchronization fails. |
Example
tw = TaskWarrior(taskrc_file="/path/to/.taskrc") tw.synchronize() # requires sync.* settings in taskrc
get_info()
¶
Get comprehensive TaskWarrior configuration information.
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
Dictionary with the following keys: |
dict[str, Any]
|
|
dict[str, Any]
|
|
dict[str, Any]
|
|
dict[str, Any]
|
|
dict[str, Any]
|
|
dict[str, Any]
|
|
dict[str, Any]
|
|
dict[str, Any]
|
|
dict[str, Any]
|
|
dict[str, Any]
|
|
dict[str, Any]
|
|
dict[str, Any]
|
|
dict[str, Any]
|
|
Example
info = tw.get_info() print(info["backend_type"]) print(info["data_location"])
task_calc(date_str)
¶
Calculate a TaskWarrior date expression.
Uses TaskWarrior's date calculation engine to evaluate date expressions like "today + 2weeks".
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
date_str
|
str
|
The date expression to calculate. |
required |
Returns:
| Type | Description |
|---|---|
str
|
The calculated date as an ISO format string. |
Raises:
| Type | Description |
|---|---|
TaskWarriorError
|
If calculation fails. |
Example
result = tw.task_calc("today + 2weeks") print(result) # "2026-02-14T00:00:00"
date_validator(date_str)
¶
Validate a TaskWarrior date expression.
Checks if a string is a valid TaskWarrior date format.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
date_str
|
str
|
The date expression to validate. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if valid, False otherwise. |
Example
tw.date_validator("next monday") # True tw.date_validator("invalid") # False
reload_udas()
¶
Reload UDA definitions from the taskrc file.
Use this method to refresh UDA definitions if they have been modified externally (e.g., by another program or manual edit).
Example
tw.reload_udas() names = tw.get_uda_names()
get_uda_names()
¶
Get all defined UDA names.
Returns:
| Type | Description |
|---|---|
set[str]
|
Set of UDA names currently defined in taskrc. |
Example
names = tw.get_uda_names() print(names) # {"severity", "estimate", "customer"}
get_uda_config(name)
¶
Get the configuration for a specific UDA.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
The name of the UDA to retrieve. |
required |
Returns:
| Type | Description |
|---|---|
UdaConfig | None
|
The UdaConfig if found, None otherwise. |
Example
config = tw.get_uda_config("severity") if config: ... print(config.type) # UdaType.STRING ... print(config.values) # ["low", "medium", "high"]
get_udas()
¶
Get full UDA definitions.
Returns:
| Type | Description |
|---|---|
list[UdaConfig]
|
List of UdaConfig objects for all defined UDAs. |
define_uda(uda)
¶
Define a new UDA via the TaskWarrior facade.
Delegates to UdaService.define_uda which performs the necessary TaskWarrior config writes and registers the UDA in the local registry.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
uda
|
UdaConfig
|
The UdaConfig describing the UDA to create. |
required |
Raises:
| Type | Description |
|---|---|
TaskOperationError
|
If creating the UDA via the underlying adapter fails. |
update_uda(uda)
¶
Update an existing UDA via the TaskWarrior facade.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
uda
|
UdaConfig
|
The UdaConfig with updated fields. |
required |
Raises:
| Type | Description |
|---|---|
TaskOperationError
|
If applying the update fails. |
delete_uda(uda)
¶
Delete a UDA via the TaskWarrior facade.
Delegates to UdaService.delete_uda which removes TaskWarrior config keys and the UDA from the local registry.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
uda
|
UdaConfig
|
The UdaConfig identifying the UDA to remove. |
required |
Raises:
| Type | Description |
|---|---|
TaskOperationError
|
If deletion fails for reasons other than missing keys. |
get_projects()
¶
Get all projects defined in TaskWarrior.
Returns:
| Type | Description |
|---|---|
list[str]
|
List of project names. |
Example
projects = tw.get_projects() print(projects) ['dmc.fil.aretordre', 'dmc.fil.aprocess', 'perso', 'perso.orl', 'pro']
get_tags(include_virtual_tags=False)
¶
Get all tags defined in TaskWarrior.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
include_virtual_tags
|
bool
|
If |
False
|
Returns:
| Type | Description |
|---|---|
list[str]
|
List of tag names. |
get_context_tags()
¶
Return tags that follow the @ context convention.
This is a convenience filter for user-defined tags such as @work.