- Python 98.5%
- Just 1.5%
- Task forest with deadline management (hard/soft) - JSON output for agents - No external dependencies - XDG-compliant storage with atomic writes |
||
|---|---|---|
| skill | ||
| src/tasker | ||
| tests | ||
| .gitignore | ||
| .python-version | ||
| justfile | ||
| pyproject.toml | ||
| README.md | ||
| uv.lock | ||
tasker
A command line task manager. Tasks form a forest: each task can have subtasks,
and those can have subtasks, to any depth. Tables for humans, --json for
agents. Python standard library only, no dependencies.
Install
The project is managed with uv; tasks run through
just. Bare just lists every recipe.
just # list recipes
just install # uv tool install --force . -> provides the `tasker` command
just install-skill # copy skill/SKILL.md to ~/.claude/skills/tasker/
just test # run the test suite
just test-oldest # run it on the oldest local interpreter (3.12)
just build # sdist + wheel into dist/
Development without installing: uv sync once, then uv run tasker ....
Storage
One JSON file, per the XDG Base Directory spec:
$XDG_DATA_HOME/tasker/tasks.json # default ~/.local/share/tasker/tasks.json
Writes are atomic (temp file in the same directory, then os.replace). The file
carries a version field for future migrations. A corrupt file is never
overwritten: tasker copies it to tasks.json.bak, reports the problem and
exits 3.
Tasks
| Field | Notes |
|---|---|
id |
unique across the forest, never reused |
name |
short indicator of the task |
description |
long field: context, links, how to track the task down |
deadline |
date (required), time (optional), kind = hard or soft |
done |
completion status |
subtasks |
recursive list of tasks |
A hard deadline must be met. A soft deadline may slip a little but is
best met. soft is the default.
Commands
tasker add NAME [--desc TEXT] [--deadline DATE[THH:MM]] [--hard|--soft] [--parent ID]
tasker list [--all] [--tree] [--due DATE] [--overdue]
tasker show ID
tasker edit ID [--name NAME] [--desc TEXT] [--deadline D] [--hard|--soft] [--no-deadline]
tasker done ID | tasker undone ID
tasker rm ID [--force]
tasker move ID (--parent ID | --root)
Add --json to any command for machine readable output.
$ tasker add "Ship tax report" --deadline 2026-08-15T14:00 --hard
added 1: Ship tax report
$ tasker add "Collect invoices" --parent 1
added 2 under 1: Collect invoices
$ tasker list --tree
ID Name Deadline Done Subtasks
-- -------------------- ------------------ ---- --------
1 Ship tax report 2026-08-15 14:00 ! no 1/1
2 └ Collect invoices no
! marks a hard deadline, ~ a soft one. The Done column shows LATE for an
open task past its deadline. Subtasks is open/total over the whole subtree.
list shows open tasks only unless --all, sorted overdue first and undated
last.
Exit codes
| Code | Meaning |
|---|---|
| 0 | success |
| 1 | usage or validation error |
| 2 | task id not found |
| 3 | storage error |
With --json, errors print {"error": "..."} to stderr and stdout stays empty.
Layout
src/tasker/model.py Task and Deadline, validation, (de)serialization
src/tasker/store.py XDG paths, load/save, atomic write, corrupt-file handling
src/tasker/ops.py forest operations: find, add, move, prune, sort (no I/O)
src/tasker/render.py table, tree and JSON rendering
src/tasker/cli.py argparse wiring, command dispatch, exit codes
tests/ unittest suite (stdlib only; CLI tests use subprocess)
skill/SKILL.md instructions that teach an agent to drive the CLI
justfile task recipes; pyproject.toml + uv.lock define the project