A cross-platform to-do list manager with encrypted peer-to-peer synchronization.
- Multiple lists - Organize tasks into separate lists with private/shared control
- Priority levels - High, normal, and low priority with color coding
- Due dates - Date picker with overdue highlighting and filtering
- Search and filter - Real-time filtering of todo items
- Undo/redo - Full undo/redo for all operations
- Encrypted sync - AES-256-GCM encryption with Ed25519 key exchange
- Device management - Track peers by fingerprint with trust levels (normal/trusted/blocked)
- Sync groups - Organize devices into groups and control which lists sync where
- Auto-sync - Debounced push after changes and periodic full sync on configurable timers
- Offline queue - Queue syncs for offline devices, auto-execute when they come online
- Auto-discovery - Find other instances on your network via mDNS/Zeroconf
- Dark/light themes - WCAG AA contrast-compliant themes with system-following
- Cross-platform - Linux, macOS, and Windows support
- Python 3.11 or later
- PyQt6
Download the latest release for your platform from the Releases page.
-
Download
pytodo-qt-VERSION-macos-arm64.dmg(Apple Silicon) orpytodo-qt-VERSION-macos-x86_64.dmg(Intel) -
Open the DMG — a window appears with the app icon and an Applications shortcut
-
Drag
pytodo-qt.apponto the Applications shortcut -
Eject the DMG, open
/Applications, and locate the app -
First run only — pick whichever unblock flow matches your macOS version:
macOS Sequoia (15.x) and later — Apple removed the right-click → Open bypass. Use this flow:
- Double-click the app. macOS shows "pytodo-qt Not Opened — Apple could not verify..." with only Done / Move to Trash buttons. Click Done.
- Open System Settings → Privacy & Security.
- Scroll to the Security section. You'll see "pytodo-qt was blocked to protect your Mac". Click Open Anyway.
- Enter your password when prompted, then click Open on the re-prompt.
macOS Sonoma (14.x) and earlier — the legacy bypass still works:
- Right-click the app → Open → click Open in the confirmation dialog → enter your password → check Always allow.
Command-line shortcut (any macOS version) — strip the quarantine attribute directly:
xattr -rd com.apple.quarantine /Applications/pytodo-qt.app
Then double-click normally.
-
After the first approval, open the app normally by double-clicking.
Note: The app is ad-hoc signed (not notarized with an Apple Developer ID), which is why macOS requires explicit first-launch approval. This is standard for open-source software distributed outside the App Store. When upgrading to a new version, drag-replace the existing
/Applications/pytodo-qt.appwith the new one and re-run whichever approval flow above matches your macOS version.
Two formats are provided for each architecture (x86_64 and arm64).
AppImage — single-file, self-contained, no install required:
- Download
pytodo-qt-VERSION-linux-x86_64.AppImage(or-linux-arm64.AppImage) - Make it executable:
chmod +x pytodo-qt-VERSION-linux-x86_64.AppImage - Run it:
./pytodo-qt-VERSION-linux-x86_64.AppImage
If your distribution dropped libfuse2 (Ubuntu 22.04+, Fedora 38+), pass --appimage-extract-and-run the first time, or install libfuse2 with your package manager.
Tarball — traditional install to ~/.local/:
- Download
pytodo-qt-VERSION-linux-x86_64.tar.gz(or-linux-arm64.tar.gz) - Extract:
tar -xzf pytodo-qt-VERSION-linux-*.tar.gz - Run the install script:
cd pytodo-qt-*/ && ./install.sh - Or run directly:
./pytodo-qt
The install script places the binary in ~/.local/bin/ and creates a desktop entry.
To uninstall: ~/.local/lib/pytodo-qt/uninstall.sh (or run ./uninstall.sh from the extracted archive)
Our AppImage ships with the PyTodo-Qt logo baked in (.DirIcon, root PNG, desktop entry at usr/share/applications/). Whether the icon actually appears next to the .AppImage file in your file manager depends on what your desktop environment has installed — the AppImage ecosystem deliberately keeps this opt-in rather than patching every runtime. Pick whichever of the three fixes below matches your setup:
-
KDE Plasma (Dolphin, Krusader): install
kio-extrasandlibappimage— most KDE distributions already ship them. Dolphin will read the embedded.DirIcondirectly and no further action is needed. -
GNOME / Cinnamon / XFCE / MATE / elementary (Nautilus, Nemo, Thunar, Caja, Files): install
xapp-thumbnailers. It ships by default on Linux Mint and Cinnamon; on Ubuntu, Fedora, Debian, and Arch you will need to install it explicitly (sudo apt install xapp-thumbnailers, etc.). Once installed, thumbnails of.AppImagefiles render with the embedded icon. -
Any desktop, "just works" path: install AppImageLauncher. Double-clicking any AppImage the first time will prompt you to integrate it; it then moves the file to
~/Applications/, extracts the icon, and creates a real desktop entry. From that point on every file manager shows the right icon because the AppImage is a registered application.
None of the above require changes to the AppImage itself — PyTodo-Qt already carries all the metadata these tools look for.
Two formats are provided:
Installer (recommended) — installs per-user, creates Start Menu entry, registers for uninstall:
- Download
pytodo-qt-VERSION-windows-x86_64-setup.exe - Double-click the installer and follow the prompts. No admin rights required — the default install directory is under your user profile, and the installer adds an entry to Windows' "Installed apps" list for clean uninstallation later.
- Optionally enable the "Create desktop icon" checkbox on the Select Additional Tasks page.
Zip — portable, no install required:
- Download
pytodo-qt-VERSION-windows-x86_64.zip - Extract the zip file to any directory (e.g. your Desktop, a USB drive, or
%LOCALAPPDATA%) - Run
pytodo-qt.exefrom the extracted folder
Note: The installer and the binaries inside the zip are not code-signed. Windows SmartScreen may show a "Windows protected your PC" warning on first launch — click More info → Run anyway.
Every artifact ships with a sibling <filename>.sha256 file in the standard sha256sum -c / shasum -a 256 -c compatible format. To verify a download:
# Linux / WSL
sha256sum -c pytodo-qt-VERSION-linux-x86_64.tar.gz.sha256
# macOS
shasum -a 256 -c pytodo-qt-VERSION-macos-x86_64.dmg.sha256
# Windows PowerShell
(Get-FileHash -Algorithm SHA256 pytodo-qt-VERSION-windows-x86_64-setup.exe).Hash.ToLower()
# Then compare against the hash printed in the .sha256 filepipx install pytodo-qt # recommended
pip install pytodo-qt # alternativegit clone https://github.com/berrym/pytodo-qt.git
cd pytodo-qt
pip install .pip install -e ".[dev]"pytodo-qtServer Options:
-s, --server {yes,no} enable/disable network server
--pull {yes,no} allow remote pull requests
--push {yes,no} allow remote push requests
-i, --ip IP server bind address
-p, --port PORT server port
Discovery Options:
-d, --discovery {yes,no} enable/disable mDNS discovery
Appearance Options:
-t, --theme {light,dark,system}
Configuration is stored in XDG-compliant locations:
| Platform | Config | Data |
|---|---|---|
| Linux | ~/.config/pytodo-qt/ |
~/.local/share/pytodo-qt/ |
| macOS | ~/Library/Application Support/pytodo-qt/ |
same |
| Windows | %APPDATA%\pytodo-qt\ |
same |
[database]
active_list = ""
sort_key = "priority"
reverse_sort = false
[server]
enabled = true
address = "0.0.0.0"
port = 5364
allow_pull = true
allow_push = true
[discovery]
enabled = true
service_name = "" # defaults to pytodo-{hostname}
auto_sync_trusted = false # auto-sync when trusted devices come online
auto_sync_delay = 0 # seconds to debounce before auto-push (0 = disabled)
auto_sync_interval = 0 # minutes between periodic full syncs (0 = disabled)
[appearance]
theme = "system" # light, dark, systempytodo-qt uses a secure peer-to-peer protocol for syncing between instances:
- Discovery - Instances advertise themselves via mDNS (
_pytodo._tcp.local.) - Key exchange - Ed25519 identity keys with X25519 ephemeral session keys
- Encryption - All data encrypted with AES-256-GCM
- Merge - Last-write-wins conflict resolution with UUID-based items
- Device management - Track peers with trust levels and organize into sync groups
- Sync rules - Control which lists sync to which device groups
- Auto-sync - Debounced push after changes, periodic full sync, and sync on trusted device discovery
- Offline queue - Queue syncs for offline devices, auto-execute when they come online
Identity keys are stored in your system keyring (GNOME Keyring, macOS Keychain, Windows Credential Locker).
# Install dev dependencies
pip install -e ".[dev]"
# Run tests
pytest
# Lint and format
ruff check src/ tests/
ruff format src/ tests/
# Type check
basedpyright src/GPLv3 or later. See COPYING for details.
Copyright 2024-2026 Michael Berry trismegustis@gmail.com