Skip to main content

mdtodo

mdtodo is a command-line todo manager that keeps everything in one plain markdown file. Headings are projects and checkbox items are tasks. You can edit the file in any editor, or use the mdtodo commands. Either way, it stays readable markdown.

- [ ] Call the bank due:2026-10-20

## Website
- [ ] Write landing copy @active due:2026-10-18
- [ ] Pick a color palette @next
  - [ ] Shortlist 3 palettes
- [x] Buy domain
  • [ ] means open, and [x] means completed.
  • @active marks a task you're working on now. @next adds a task to the pool of tasks you plan to pick up next.
  • due:YYYY-MM-DD sets a deadline. Open tasks are flagged as overdue, or as due soon (today through the next 3 days).
  • Tasks above the first heading go into the Inbox project. Prose, notes, and code blocks are ignored.

Listings show each task with its reference. A subtask is labelled with its parent's name, as <parent>: <task>, so you can tell which task it belongs to:

$ mdtodo list --project Website
## Website
bbdb3a  OVERDUE  ACTIVE  Write landing copy  (2 days overdue, 2026-10-18)
b1b77f  NEXT  Pick a color palette
  aa0d81  Pick a color palette: Shortlist 3 palettes

Each task line starts with its ref, then a marker for how urgent it is: OVERDUE, DUE SOON, ACTIVE, or NEXT. Deadlines read relative to today ("due tomorrow", "2 days overdue") next to the date. The summary lists Overdue, Due soon, Active, then Next, and shows each task only once, in its most urgent section.

The full syntax is in specs/001-markdown-todo-manager/contracts/file-format.md.

Install

With uv installed:

uv tool install mdtodo   # puts `mdtodo` on your PATH (~/.local/bin)
mdtodo --version

If you don't have a suitable Python, uv downloads one for you.

uv tool install mdtodo==X.Y.Z   # install a specific version
uv tool upgrade mdtodo          # move to the latest release
uv tool uninstall mdtodo        # remove the command

Uninstalling removes only the command. Your todo file (~/tracker.md, or whatever --file or MDTODO_FILE points at) is left untouched.

Switching from an editable install: if you installed with uv tool install --editable ., run uv tool uninstall mdtodo first, or replace it in one step with uv tool install --force mdtodo.

Which file is used

The first match wins:

  1. --file PATH, which can go before or after the command;
  2. the MDTODO_FILE environment variable;
  3. ~/tracker.md.

If you used an earlier version that read ~/TODO.md, rename that file to ~/tracker.md, or point --file or MDTODO_FILE at it.

mdtodo init creates a starter file. Nothing else ever creates the file.

Colour

On a terminal, urgent tasks are coloured: overdue in bold red, due soon in bold magenta, active in bold green, and next in green. Titles are bold, and everything else is normal text. Only bold and the terminal's standard named colours are used, so your theme picks the exact shades and the output stays readable on light and dark backgrounds. Colour only repeats what the text already says, so nothing is lost without it.

--color auto|always|never (before or after the command) chooses when to use it. With auto, the default, colour is off when output is piped or redirected, when NO_COLOR is set, or when TERM=dumb. FORCE_COLOR is not read; use --color always to force colour, for example mdtodo --color always | less -R.

Commands

Command What it does
mdtodo / mdtodo summary Overdue, Due soon, Active, and Next tasks (each listed once), plus counts per project
mdtodo list [--all] [--project NAME] Tasks grouped by project, each with its reference
mdtodo next The next pool, ordered by deadline
mdtodo due Open tasks ordered by deadline
mdtodo start REF / mdtodo stop REF Add or remove @active
mdtodo next add REF / mdtodo next rm REF Add or remove @next
mdtodo done REF Check the box, and remove @active and @next
mdtodo init Create a starter file

REF is the 6-character reference shown in every listing. It stays the same when markers change. If you edit a task's text, its reference changes, and the old one is refused rather than applied to the wrong task. Each command changes only the task's own line. If the file changed while the command was running, nothing is written.

Details, including output formats and exit codes, are in contracts/cli.md.

Development

uv sync
uv tool install --editable .       # installs this working tree as the `mdtodo` command
scripts/check.sh                   # format, lint, mypy --strict, tests (coverage ≥ 80%)
uv run pytest -m perf --no-cov     # timing checks (SC-002), kept out of the default run

The design documents are in specs/001-markdown-todo-manager/, and the project principles are in .specify/memory/constitution.md.

Releasing

Releases go to PyPI with scripts/release.sh. See docs/releasing.md.

Metadata

Release files for mdtodo 0.4.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for mdtodo 0.4.0
File Size Uploaded Provenance
mdtodo-0.4.0.tar.gz 15.0 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for mdtodo 0.4.0
File Interpreter ABI Platform
mdtodo-0.4.0-py3-none-any.whl Python 3 none any Details

Total release size: 34.2 kB

Release files / mdtodo-0.4.0.tar.gz

Download URL mdtodo-0.4.0.tar.gz
Size 15.0 kB
Tags Source
SHA-256 checksum
How to use checksums
ffb9b2746af1ed58bbfe262ad2d7f849a62a447f0e62fdaf66f5f085ae48d585
BLAKE2b-256 checksum
How to use checksums
6637b04160fcc3cf2a304d843c03351ed26e41c078492fa072c81245c300b17a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.9.16 {"installer":{"name":"uv","version":"0.9.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / mdtodo-0.4.0-py3-none-any.whl

Download URL mdtodo-0.4.0-py3-none-any.whl
Size 19.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4c880be1ca559e0861484141238f7e4c05182954b80f9d16e03ebdabfb517879
BLAKE2b-256 checksum
How to use checksums
7dd40c1c57421c7bdab3c7edfbbd174fbc79d521c0b069e0a350617909cce722
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.9.16 {"installer":{"name":"uv","version":"0.9.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Security for mdtodo 0.4.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page