toduck
Docker app from CatDuck's Repository
Overview
Readme
View on GitHubToduck
Toduck is a local first task manager with a responsive Web UI, repeating tasks, categories, search, import and export, optional self hosted synchronization, and an Android companion app.
Renamed from Cat2Duck. The GitHub repository, the app brand, and the container image were renamed to Toduck in October 2026, and the old internal name (Cadence) was retired with it — including the Android app id, the server environment variables, and the browser storage keys. The old repository URL redirects here, and the old image
ghcr.io/catduckgnaf/cat2duckis superseded byghcr.io/catduckgnaf/toduck. Existing installs need a few one-time steps: Web browser data migrates automatically on first load, and oldcadence.jsonexports still import (new exports aretoduck.json); server installs must rename their environment variables (see the upgrade note in the self hosting guide); and the Android app is a new app identity — uninstall the old app and install Toduck fresh (see the Android guide).
Features
- Local first task storage in the browser
- Feed, day, upcoming, overdue, later, repeats, and completed views
- Repeating schedules and category filters
- JSON backup and restore
- Optional conflict safe synchronization through the bundled Node server
- Docker and Unraid packaging
- Android client and home screen widget
Development
Requirements: Node.js 22 or newer and npm.
npm ci
npm run dev
The development app listens on http://localhost:8080.
Quality checks
npm test
npm run lint
npm run typecheck
npm run build
npm run test:e2e
Playwright browser tests exercise the core task flow at desktop and 390 by 844 mobile viewports.
Self hosting
The bundled container serves both the compiled Web UI and synchronization API from one origin.
export TODUCK_TOKEN="$(openssl rand -hex 32)"
docker compose -f selfhost/docker-compose.yml up --build -d
Open http://localhost:8793. The host address and port can be changed with TODUCK_BIND and TODUCK_PORT.
A prebuilt image is published to ghcr.io/catduckgnaf/toduck (amd64 and arm64); docker compose -f selfhost/docker-compose.yml pull uses it instead of building locally.
See the self hosting guide for authentication, CORS, backups, API behavior, Docker, and Unraid instructions.
Android
See the Android guide for build and connection instructions.
Repository layout
src/components/toduck: task manager UIsrc/lib/toduck: task model, state, persistence, and sync clientselfhost: standalone server, Docker image, Compose file, and Unraid templateandroid: Android cliente2e: Playwright browser tests
Data and security
Tasks remain in browser storage unless synchronization is configured. The server address may be remembered, but the bearer token is kept only in the current browser session and is cleared when disconnected. Use a unique token of at least 32 characters and put TLS or a trusted private network in front of any remote deployment.
License
Toduck is open source software licensed under the MIT License.
Categories
Related apps
Explore more like this
Explore allDetails
ghcr.io/catduckgnaf/toduck:latestRuntime arguments
- Web UI
http://[IP]:[PORT:8787]/- Network
bridge- Shell
sh- Privileged
- false
Template configuration
Host port for the Web UI and sync API (use 8793 to avoid a collision with Readarr on 8787)
- Target
- 8787
- Default
- 8793
- Value
- 8793
Persistent directory for state.json and its state.json.bak backup. Back this up.
- Target
- /data
- Default
- /mnt/user/appdata/toduck
- Value
- /mnt/user/appdata/toduck
Secret. Admin bearer token used by Web and Android clients to sync; must be at least 32 characters (for example the output of: openssl rand -hex 32). The container refuses to start without it.
- Target
- TODUCK_TOKEN
Optional comma-separated list of origins allowed to call the sync API cross-origin, for example https://tasks.example.com. Leave empty for the normal same-origin Web UI and app use.
- Target
- TODUCK_ALLOWED_ORIGINS
Internal container port
- Target
- PORT
- Default
- 8787
- Value
- 8787
Internal path to the JSON state file
- Target
- DATA_PATH
- Default
- /data/state.json
- Value
- /data/state.json
Internal path to the built Web UI
- Target
- STATIC_DIR
- Default
- /app/static
- Value
- /app/static