A modern Python library for TaskWarrior v3.x task management.
No task binary required. pytaskwarrior uses
taskchampion3-py-dev — Rust bindings
to the taskchampion storage engine — for direct, high-performance SQLite access.
- No external binary — reads/writes TaskWarrior's SQLite database directly
- Full CRUD operations — Create, read, update, delete tasks
- Type-safe — Pydantic models with full type hints
- Context management — Define, apply, and switch contexts (reads/writes
.taskrc) - UDA support — User Defined Attributes
- Virtual tags —
+OVERDUE,+DUE,+TODAY,+WEEK,+BLOCKED,+READY, and 20+ more - Date expressions —
due.before:tomorrow,due.after:eom, compound expressions (now + P3D) - Recurring tasks — Full recurrence support
- Annotations — Add notes to tasks
- Optional CLI fallback — Pass
task_cmd="task"to use the classic CLI adapter
- Python 3.9+
taskchampion3-py-dev>= 3.0.1.3 (installed automatically)
The task binary is not required for the default adapter.
pip install pytaskwarriorOr install from source:
git clone https://github.com/sznicolas/pytaskwarrior.git
cd pytaskwarrior
uv syncfrom taskwarrior import TaskWarrior, TaskInputDTO, Priority
# No binary needed — uses taskchampion SQLite backend directly
tw = TaskWarrior()
# Create a task
task = tw.add_task(TaskInputDTO(
description="Finish project report",
priority=Priority.HIGH,
project="work",
tags=["urgent"],
due="friday",
))
print(f"Created: {task.uuid}")
# Query tasks
for t in tw.get_tasks("project:work"):
print(f"[{t.priority or '-'}] {t.description}")
# Virtual tag filtering
overdue = tw.get_tasks("+OVERDUE")
due_soon = tw.get_tasks("due.before:eow")
# Complete a task
tw.done_task(task.uuid)# Explicit CLI mode — requires the task binary
tw = TaskWarrior(task_cmd="task")
# Custom paths
tw = TaskWarrior(
taskrc_file="/path/to/.taskrc",
data_location="/path/to/task/data",
)config_store is the live interface to the taskrc file. Changes made via
set_value() or set_sync_config() are immediately effective on the next
adapter call — no restart or adapter recreation required.
tw = TaskWarrior()
# Configure remote sync at runtime
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
# Or replace the whole sync block at once
tw.config_store.set_sync_config({
"sync.local.server_dir": "/mnt/shared/taskserver",
})
tw.synchronize()Note: Changing
data_locationat runtime is not supported. Create a newTaskWarriorinstance if you need a different data directory.
Thread Safety:
TaskChampionAdapterenforces thread affinity — it must be used only from the thread that created it. For multi-threaded environments (e.g., FastAPI sync endpoints), create one adapter per thread. For concurrent read access, useAccessMode.ReadOnly. See TaskChampion Adapter docs for details.
TaskWarrior (facade)
├── TaskChampionAdapter ← default: direct SQLite via taskchampion3-py-dev
│ ├── CRUD operations (add/get/modify/delete tasks)
│ ├── Filtering (tc_filter.py — Python reimplementation of TW filters)
│ └── Date resolution (date_resolver.py — Python reimplementation of TW dates)
├── ConfigStore ← reads/writes ~/.taskrc
│ ├── ContextService ← define/apply/delete contexts
│ └── UdaService ← define/delete UDAs
└── TaskWarriorAdapter ← optional CLI fallback (task_cmd="task")
| Token | Example | Description |
|---|---|---|
+tag / -tag |
+urgent -someday |
Include / exclude by tag |
+VIRTUAL |
+OVERDUE, +DUE, +TODAY |
Virtual tags (computed) |
status:X |
status:pending |
Status filter |
project:X |
project:work |
Project (hierarchical) |
priority:X |
priority:H |
Priority |
due.before:X |
due.before:tomorrow |
Date range |
due.after:X |
due.after:eom |
Date range |
due.by:X |
due.by:friday |
Date range (inclusive) |
- Getting Started — Installation and setup
- TaskChampion Adapter — Technical details
- API Reference — Full API documentation
- Examples — More usage examples