Skip to content

Repository files navigation

Task Manager

CI

Task Manager is a small self-hosted task tracker with a command-line client, a FastAPI service, and SQLite storage. It supports task status, ownership, due dates, work notes, and text or date-based searches.

Features

  • Create, inspect, update, search, and delete tasks from the CLI.
  • Track todo, in_progress, and completed tasks.
  • Store task descriptions, owners, due dates, and timestamped work notes.
  • Edit long descriptions with $EDITOR.
  • Run the API as a systemd service or a Docker container.
  • Persist data in a configurable SQLite database.

Requirements

  • Python 3.10 or newer for Python installation and development.
  • uv for the reproducible development workflow.
  • Fedora tooling when building the RPM locally.

Python installation

Install both console commands from a checkout:

uv tool install .

This provides:

  • task: the command-line client.
  • task_server: the FastAPI server.

The client connects to http://localhost:8000 by default. To use another server, create ~/.taskrc:

[default]
api_url = https://tasks.example.com

CLI usage

Start the server before using the client:

TASK_DB_PATH=./task_manager.db task_server

Common commands:

task ping
task add --title "Review pull request" --description "Review API changes"
task list
task show --id 1
task update --id 1 --status in_progress
task note --id 1 --note "Finished the API review"
task search --text "pull request"
task delete --id 1

Run task --help or task <command> --help for the complete options.

Docker

The image is published to both Docker Hub and GitHub Container Registry:

  • edimatt/task-manager
  • ghcr.io/edimatt/task-manager

Run it with a named volume for the SQLite database:

docker run --detach \
  --name task-manager \
  --publish 127.0.0.1:8000:8000 \
  --volume task-manager-data:/var/lib/task_manager \
  edimatt/task-manager:latest

Verify the service:

curl http://localhost:8000/ping

Build an image locally:

make docker FEDORA_VERSION=41

The docker target has rpm as a prerequisite. It automatically runs the tests, builds the source distribution, creates the RPM, and only then builds the container image with that RPM:

test + sdist -> rpm -> docker image

Run this target on Fedora with the RPM development tools and Docker installed. The RPM is built for the host Fedora release, so pass the same release through FEDORA_VERSION when it differs from the Fedora 44 default. The Docker build uses that value for both the base image tag and the RPM .fc<release> suffix, preventing an RPM for another Fedora release from being installed accidentally.

Override the local image tag when needed:

make docker FEDORA_VERSION=41 DOCKER_IMAGE=task-manager:dev

The API has no authentication or TLS termination. Do not expose it directly to an untrusted network; place it behind an appropriately configured reverse proxy or firewall.

The container runs with the fixed UID and GID 10001. For Kubernetes PersistentVolumes, use a pod-level security context such as:

securityContext:
  runAsNonRoot: true
  runAsUser: 10001
  runAsGroup: 10001
  fsGroup: 10001

RPM and systemd

Build the Fedora RPM:

make rpm

pyproject.toml is the single source of truth for the application version. Display the current version with either command:

uv version --short
make version

Set a specific version or increment the patch version with:

uv version 0.1.1
uv version --bump patch

The Makefile and RPM build automatically consume this value. In RPM packaging, Version is the upstream application version, while Release identifies the packaging revision and is maintained separately.

Install it:

sudo dnf install dist/task_manager-*.rpm
sudo systemctl enable --now task_server.service

The service runs as taskd and stores its database at:

/var/lib/task_manager/task_manager.db

The RPM creates taskd only when the account does not already exist. It does not remove the account during package erasure, preserving ownership of existing task data and avoiding deletion of an externally managed service account.

Development

Create the locked development environment:

uv sync --locked --extra dev

Run lint and tests:

uv run --no-sync ruff check src test
uv run --no-sync pytest

Run a development server:

TASK_DB_PATH=./dev.db uv run task_server

Build the source distribution:

uv build --sdist

Continuous integration

Pull requests run lint and tests. Pushes to main additionally build the source distribution and RPM, then install that RPM into a Docker image and publish:

  • edimatt/task-manager:latest
  • edimatt/task-manager:<commit-sha>
  • ghcr.io/edimatt/task-manager:latest
  • ghcr.io/edimatt/task-manager:<commit-sha>

Docker Hub publishing requires the DOCKERHUB_TOKEN GitHub Actions secret. GHCR publishing uses the repository-scoped GITHUB_TOKEN.

API documentation

While the service is running, interactive OpenAPI documentation is available at:

http://localhost:8000/docs

License

Task Manager is licensed under the MIT License.

About

Self-hosted task manager with a FastAPI API, Python CLI, SQLite storage, RPM packaging, Docker image, and automated CI/CD.

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages