Fast, minimal command-line client for Microsoft To-Do
Project description
microsoft-todo-cli
Fast, minimal Microsoft To-Do CLI built for LLM agents, automation, and human use.
$ todo tasks
[0] Buy groceries
[1] Call mom ! (due: tomorrow)
[2] Review PR #42
[x] Check tests
[ ] Add documentation
$ todo new "Deploy v2.0" -d friday -r 9am -I
Created task 'Deploy v2.0' in 'Tasks'
$ todo complete 0
Completed task 'Buy groceries' in 'Tasks'
Install
Requirements: Python 3.10+
pip install microsoft-todo-cli
Or install from source:
git clone https://github.com/underwear/microsoft-todo-cli.git
cd microsoft-todo-cli
pip install -e .
Then configure Microsoft API access: Setup Guide (5 min)
Quick Start
todo lists # Show all lists
todo tasks # Show tasks from default list
todo tasks Work # Show tasks from "Work" list
todo new "Buy milk" # Create task
todo complete "Buy milk" # Mark done (or: todo c "Buy milk")
todo rm "Old task" # Delete
Default list: The first list returned by Microsoft To-Do API (usually "Tasks"). Specify a list explicitly with -l ListName or as a positional argument.
Short aliases: t (tasks), n (new), c (complete), d (rm) — see Aliases.
Usage
Tasks
# View
todo tasks # Default list
todo tasks Work # Specific list
todo tasks --due-today # Due today
todo tasks --overdue # Past due
todo tasks --important # High priority
todo tasks --completed # Done tasks
todo tasks --all # Everything
# Create
todo new "Task name" # Basic
todo new "Task" -l Work # In specific list
todo new "Task" -d tomorrow # With due date
todo new "Task" -r 2h # With reminder (in 2 hours)
todo new "Task" -d mon -r 9am # Due Monday, remind at 9am
todo new "Task" -I # Important
todo new "Task" -R daily # Recurring
todo new "Task" -R weekly:mon,fri # Recurring on specific days
todo new "Task" -S "Step 1" -S "Step 2" # With subtasks
todo new "Task" -N "Note content" # With note
# View single task
todo show "Task" # Show task details
todo show 0 # Show by index
# Manage
todo complete "Task" # Mark complete
todo complete 0 1 2 # Complete by index (batch)
todo uncomplete "Task" # Reopen task
todo update "Task" --title "New" # Rename
todo update "Task" -d friday -I # Change due date, make important
todo rm "Task" # Delete (asks confirmation)
todo rm "Task" -y # Delete (no confirmation)
Subtasks (Steps)
todo new-step "Task" "Step text" # Add step
todo list-steps "Task" # List steps
todo complete-step "Task" "Step" # Check off
todo uncomplete-step "Task" "Step" # Uncheck
todo rm-step "Task" 0 # Remove by index
Notes
todo note "Task" "Note content" # Add/update note
todo show-note "Task" # Display note (alias: sn)
todo clear-note "Task" # Remove note (alias: cn)
Notes are text content attached to a task. Use todo show "Task" to see the note along with other task details.
Deep Links
# Add a link to a task
todo link "Fix bug" "https://jira.company.com/browse/ZD-123" --app Jira --title ZD-123
todo link "Review PR" "https://github.com/org/repo/pull/42" --app GitHub
todo link "Discuss with team" "https://app.slack.com/..." --app Slack
# List links on a task
todo links "Fix bug"
# Remove all links from a task
todo unlink "Fix bug"
# Remove a specific link by index
todo unlink "Fix bug" --index 0
# Create a task with a link
todo new "Fix bug" --link "https://jira.company.com/browse/ZD-123"
# Use --id for automation
todo link --id "AAMk..." -l Tasks "https://jira.com/ZD-123" --app Jira
todo links --id "AAMk..." -l Tasks
todo unlink --id "AAMk..." -l Tasks
Deep links attach URLs to tasks using Microsoft To Do's linked resources API. In the To Do app, links appear as clickable "Open in {app}" buttons. Use this to connect tasks to Jira tickets, GitHub PRs, Slack threads, or any URL.
File Attachments
# Attach a file to a task
todo attach "Task" /path/to/file.pdf
todo attach "Task" /path/to/image.png -l Work
# List attachments on a task
todo attachments "Task"
todo attachments "Task" --json
# Remove all attachments from a task
todo detach "Task"
# Remove a specific attachment by index
todo detach "Task" --index 0
# Download all attachments from a task
todo download "Task"
# Download a specific attachment by index
todo download "Task" --index 0
# Download to a specific directory
todo download "Task" -o /tmp/downloads
# Create a task with an attachment
todo new "Review report" --attach /path/to/report.pdf
# Use --id for automation
todo attach --id "AAMk..." -l Tasks /path/to/file.pdf
todo attachments --id "AAMk..." -l Tasks --json
todo detach --id "AAMk..." -l Tasks
todo download --id "AAMk..." -l Tasks
File attachments use the Microsoft Graph API's todoTask attachments endpoint. Files up to 3 MB are uploaded directly; files between 3-25 MB use an upload session. The maximum attachment size is 25 MB. Attachments appear in the Microsoft To Do app UI.
Lists
todo lists # Show all lists
todo new-list "Project X" # Create list
todo rename-list "Old" "New" # Rename list
todo rm-list "Project X" # Delete list (asks confirmation)
todo rm-list "Project X" -y # Delete list (no confirmation)
Date & Time Formats
| Type | Examples |
|---|---|
| Relative | 1h, 30m, 2d, 1h30m |
| Time | 9:30, 9am, 17:00, 5:30pm |
| Days | tomorrow, monday, fri |
| Date | 2026-12-31, 31.12.2026, 12/31/2026 |
| Keywords | morning (7:00), evening (18:00) |
Recurrence Patterns
| Pattern | Description |
|---|---|
daily |
Every day |
weekly |
Every week |
monthly |
Every month |
yearly |
Every year |
weekdays |
Monday to Friday |
weekly:mon,wed,fri |
Specific days |
every 2 days |
Custom interval |
every 3 weeks |
Custom interval |
Scripting & Automation
JSON Output
Add --json to any command for machine-readable output:
todo tasks --json
todo lists --json
todo show "Task" --json
Example: todo tasks --json
{
"list": "Tasks",
"tasks": [
{
"id": "AAMkADU3...",
"title": "Buy groceries",
"status": "notStarted",
"importance": "normal",
"due_date": null,
"reminder": null,
"recurrence": null,
"steps": []
},
{
"id": "AAMkADU4...",
"title": "Call mom",
"status": "notStarted",
"importance": "high",
"due_date": "2026-02-06",
"reminder": "2026-02-06T09:00:00",
"recurrence": null,
"steps": [
{"id": "step1", "name": "Check tests", "completed": true},
{"id": "step2", "name": "Add documentation", "completed": false}
]
}
]
}
Write commands return action confirmation:
todo new "Task" --json # {"action": "created", "id": "AAMk...", "title": "Task", "list": "Tasks"}
todo complete "Task" --json # {"action": "completed", "id": "AAMk...", "title": "Task", "list": "Tasks"}
todo rm "Task" -y --json # {"action": "removed", "id": "AAMk...", "title": "Task", "list": "Tasks"}
Task Identification
Tasks can be identified by name, index, or ID. Priority for reliable automation:
| Method | Stability | Use case |
|---|---|---|
--id "AAMk..." |
Stable | Scripts, automation, agents |
Index (0, 1) |
Unstable | Interactive use only |
Name ("Task") |
Unstable | Interactive use, unique names |
# Get task ID from JSON output
todo tasks --json | jq -r '.tasks[0].id'
# Show IDs inline (human-readable + IDs)
todo tasks --show-id
# Use ID in commands (requires -l for list context)
todo complete --id "AAMkADU3..." -l Tasks
todo update --id "AAMkADU3..." --title "New title"
todo rm --id "AAMkADU3..." -l Tasks -y
Example: Create and complete a task by ID
ID=$(todo new "Deploy v2.0" -l Work --json | jq -r '.id')
# ... later ...
todo complete --id "$ID" -l Work
Exit Codes
| Code | Meaning |
|---|---|
0 |
Success |
1 |
General error (invalid arguments, task not found, API error) |
With --json: stdout contains only valid JSON on success. Errors go to stderr.
Tips for Scripts and Agents
- Prefer
--idover names/indexes: Names can have duplicates (first match wins). Indexes change as tasks are added/completed/reordered. - Always use
-l ListNamewith--idto specify list context. - Capture IDs on creation: Store the ID from
todo new --jsonfor later operations. - Use
--jsonfor parsing: Human-readable output format may change between versions. - Use
-yflag withrmcommands to skip confirmation prompts.
Aliases
| Alias | Command | Alias | Command |
|---|---|---|---|
t |
tasks |
d |
rm |
n |
new |
newl |
new-list |
c |
complete |
reopen |
uncomplete |
sn |
show-note |
cn |
clear-note |
todo t # = todo tasks
todo n "Task" -d fri # = todo new "Task" -d fri
todo c 0 1 2 # = todo complete 0 1 2
todo d "Old" -y # = todo rm "Old" -y
Claude Code
A skill for Claude Code is available:
todo skill — enables Claude to manage your Microsoft To-Do tasks directly.
Credits
Forked from kiblee/tod0 with a redesigned CLI.
License
MIT
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file microsoft_todo_cli-1.4.1.tar.gz.
File metadata
- Download URL: microsoft_todo_cli-1.4.1.tar.gz
- Upload date:
- Size: 51.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3b5eba0d46d03bf5e020cd856c4434a10e764a049d1e8d331ae1ad5e052fed16
|
|
| MD5 |
18284519f9b4568329ed146c95fb2eb7
|
|
| BLAKE2b-256 |
df3f3bdfa2b83f36dd9393d74e075bf8ffde690887b45942b21bffbf1189d7c1
|
File details
Details for the file microsoft_todo_cli-1.4.1-py3-none-any.whl.
File metadata
- Download URL: microsoft_todo_cli-1.4.1-py3-none-any.whl
- Upload date:
- Size: 61.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a75513e5653c444f9edc35bb6c559bb59e0b14dfd6d5fbe7351f598596f06a53
|
|
| MD5 |
8f20134749f5af2f2ac738ce7722781d
|
|
| BLAKE2b-256 |
523c1efe197c6d3eb8100835026fc90bf97e0540e66aa5b36aa7b15fab9e872e
|