Install any skill in seconds. Free to start, no credit card required.
Get Started Free →A CLI skill to manage Microsoft To Do tasks via Microsoft Graph API. Supports listing, creating, completing, deleting, searching tasks and lists, viewing overdue/today/pending tasks, and exporting data.
.claude/skills/leoyeai-ms-todo-sync/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-05 | ✗→✓ | ▲ Improved | 117% | 0% |
| case-06 | ✗→✓ | ▲ Improved | 188% | 0% |
| case-07 | ✗→✓ | ▲ Improved | 322% | 0% |
| case-08 | ✗→✓ | ▲ Improved | 164% | 0% |
| case-10 | ✗→✓ | ▲ Improved | 140% | 0% |
A Microsoft To Do command-line client for managing tasks and lists via Microsoft Graph API.
pip install uv or see https://docs.astral.sh/uv/.~/.mstodo_token_cache.json (persists across sessions, auto-refreshed)~/.mstodo_device_flow.json (temporary)Before using this skill for the first time, dependencies must be installed:
bash# Navigate to skill directory cd <path-to-ms-todo-sync> # Install dependencies using uv (recommended - creates isolated environment) uv sync # Alternative: Install dependencies with pip (uses global/active Python environment) pip install -r requirements.txt
Dependencies:
msal (Microsoft Authentication Library) and requestsrequirements.txtuv creates an isolated virtual environment to avoid conflictsAfter installation, verify the setup:
bash# Check if uv can find the script uv run scripts/ms-todo-sync.py --help # Expected: Command help text should be displayed
Troubleshooting:
uv: command not found, install uv: pip install uvPython not found, install Python 3.9 or higher from https://python.orguv sync or pip install -r requirements.txtmsal library~/.mstodo_token_cache.jsonAll commands follow this pattern:
uv run scripts/ms-todo-sync.py [GLOBAL_OPTIONS] <command> [COMMAND_OPTIONS]| Option | Description | |--------|-------------| | -v, --verbose | Show detailed information (IDs, dates, notes). Must be placed BEFORE the subcommand. | | --debug | Enable debug mode to display API requests and responses. Useful for troubleshooting. Must be placed BEFORE the subcommand. |
> ⚠️ Common mistake: Global options MUST come before the subcommand. > - ✅ uv run scripts/ms-todo-sync.py -v lists > - ✅ uv run scripts/ms-todo-sync.py --debug add "Task" > - ❌ uv run scripts/ms-todo-sync.py lists -v
Authentication uses a two-step device code flow designed for non-interactive/agent environments.
login get — Get verification codebashuv run scripts/ms-todo-sync.py login get
Output example:
✓ Verification code generated
Please visit the following link to log in:
https://microsoft.com/devicelogin
Enter verification code: ABC123XYZ
Verify with command: ms-todo-sync.py login verifyAgent behavior: Present the URL and verification code to the user. Wait for the user to confirm they have completed the browser login before proceeding.
login verify — Complete loginbashuv run scripts/ms-todo-sync.py login verify
Output on success:
✓ Authentication successful! Login information saved, you will be logged in automatically next time.Output on failure:
✗ Authentication failed: <error description>> ⚠️ This command blocks until Microsoft's server confirms the user completed browser authentication. Do NOT run this until the user confirms they have completed the browser step.
Exit code: 0 on success, 1 on failure.
logout — Clear saved loginbashuv run scripts/ms-todo-sync.py logout
Only use when the user explicitly asks to switch accounts or clear login data. Under normal circumstances, the token is cached and login is automatic.
lists — List all task listsbashuv run scripts/ms-todo-sync.py lists uv run scripts/ms-todo-sync.py -v lists # with IDs and dates
Output example:
📋 Task Lists (3 total):
1. Tasks
2. Work
3. Shoppingcreate-list — Create a new listbashuv run scripts/ms-todo-sync.py create-list "<name>"
| Argument | Required | Description | |----------|----------|-------------| | name | Yes | Name of the new list |
Output: ✓ List created: <name>
delete-list — Delete a listbashuv run scripts/ms-todo-sync.py delete-list "<name>" [-y]
| Argument/Option | Required | Description | |-----------------|----------|-------------| | name | Yes | Name of the list to delete | | -y, --yes | No | Skip confirmation prompt |
> ⚠️ This is a destructive operation. Without -y, the command will prompt for confirmation. Consider asking the user before deleting important lists.
Output: ✓ List deleted: <name>
add — Add a new taskbashuv run scripts/ms-todo-sync.py add "<title>" [options]
| Option | Required | Default | Description | |--------|----------|---------|-------------| | title | Yes | — | Task title (positional argument) | | -l, --list | No | (default list) | Target list name. If not specified, uses your Microsoft To Do default list. | | -p, --priority | No | normal | Priority: low, normal, high | | -d, --due | No | — | Due date. Accepts days from now (3 or 3d) or date (2026-02-15). Note: Only date is supported, not time. | | -r, --reminder | No | — | Reminder datetime. Formats: 3h (hours), 2d (days), 2026-02-15 14:30 (date+time with space, needs quotes), 2026-02-15T14:30:00 (ISO format), 2026-02-15 (date only, defaults to 09:00). | | -R, --recurrence | No | — | Recurrence pattern. Formats: daily (every day), weekdays (Mon-Fri), weekly (every week), monthly (every month). With interval: daily:2 (every 2 days), weekly:3 (every 3 weeks), monthly:2 (every 2 months). Note: Automatically sets start date. | | -D, --description | No | — | Task description/notes | | -t, --tags | No | — | Comma-separated tags (e.g., "work,urgent") |
Behavior: If the specified list doesn't exist, it will be automatically created.
Output example:
✓ List created: Work
✓ Task added: Complete reportcomplete — Mark a task as completedbashuv run scripts/ms-todo-sync.py complete "<title>" [-l "<list>"]
| Option | Required | Default | Description | |--------|----------|---------|-------------| | title | Yes | — | Exact task title | | -l, --list | No | (default list) | List name where the task resides. If not specified, uses your default list. |
Output: ✓ Task completed: <title>
delete — Delete a taskbashuv run scripts/ms-todo-sync.py delete "<title>" [-l "<list>"] [-y]
| Option | Required | Default | Description | |--------|----------|---------|-------------| | title | Yes | — | Exact task title | | -l, --list | No | (default list) | List name. If not specified, uses your default list. | | -y, --yes | No | — | Skip confirmation prompt |
> ⚠️ This is a destructive operation. Without -y, the command will prompt for confirmation. For routine cleanup or when user intent is clear, -y can be used to avoid blocking.
Output: ✓ Task deleted: <title>
tasks — List tasks in a specific listbashuv run scripts/ms-todo-sync.py tasks "<list>" [-a]
| Option | Required | Default | Description | |--------|----------|---------|-------------| | list | Yes | — | List name (positional argument) | | -a, --all | No | — | Include completed tasks (default: only incomplete) |
Output example:
📋 Tasks in list "Work" (2 total):
1. [In Progress] Write documentation ⭐
2. [In Progress] Review PRpending — All incomplete tasks across all listsbashuv run scripts/ms-todo-sync.py pending [-g]
| Option | Required | Description | |--------|----------|-------------| | -g, --group | No | Group results by list |
Output example (with -g):
📋 All incomplete tasks (3 total):
📂 Work:
[In Progress] Write documentation ⭐
[In Progress] Review PR
📂 Shopping:
[In Progress] Buy groceriestoday — Tasks due todaybashuv run scripts/ms-todo-sync.py today
Lists incomplete tasks with due date matching today. Output: 📅 No tasks due today if none found.
overdue — Overdue tasksbashuv run scripts/ms-todo-sync.py overdue
Output example:
⚠️ Overdue tasks (1 total):
[In Progress] Submit report ⭐
List: Work
Overdue: 3 daysdetail — View full task detailsbashuv run scripts/ms-todo-sync.py detail "<title>" [-l "<list>"]
| Option | Required | Default | Description | |--------|----------|---------|-------------| | title | Yes | — | Task title (supports partial/fuzzy match) | | -l, --list | No | (default list) | List name. If not specified, uses your default list. |
When multiple tasks match, returns the most recently modified incomplete task. If all matches are completed, returns the most recently modified completed task.
search — Search tasks by keywordbashuv run scripts/ms-todo-sync.py search "<keyword>"
Searches across all lists in both task titles and notes (case-insensitive).
Output example:
🔍 Search results (1 found):
[In Progress] Write documentation ⭐
List: Workstats — Task statisticsbashuv run scripts/ms-todo-sync.py stats
Output example:
📊 Task Statistics:
Total lists: 3
Total tasks: 15
Completed: 10
Pending: 5
High priority: 2
Overdue: 1
Completion rate: 66.7%export — Export all tasks to JSONbashuv run scripts/ms-todo-sync.py export [-o "<filename>"]
| Option | Required | Default | Description | |--------|----------|---------|-------------| | -o, --output | No | todo_export.json | Output file path |
Output: ✓ Tasks exported to: <filename>
| Code | Meaning | |------|---------| | 0 | Success | | 1 | Failure (not logged in, API error, invalid arguments, etc.) |
| Error | Cause | Resolution | |-------|-------|------------| | ❌ Not logged in | No cached token or token expired | Run login get then login verify | | ModuleNotFoundError: No module named 'msal' | Dependencies not installed | Run uv sync or pip install -r requirements.txt | | ❌ List not found: <name> | Specified list does not exist | Check list name with lists command | | ❌ Task not found: <name> | No task with exact matching title | Check task title with tasks or search | | ❌ Error: <message> | API or network error | Retry; check network; use --debug for details |
cd to the directory containing this SKILL.md before running commands.uv sync to ensure all dependencies are installed.lists to see available task listsdelete and delete-list commands:-y flag to skip confirmation ONLY when:-y-v and --debug must come BEFORE the subcommand, not after.login verify automatically: This command blocks waiting for user browser interaction. Only call it after the user confirms completion.lists) to verify authentication. Handle the "Not logged in" error gracefully.1. cd <skill_directory>
2. uv sync # Ensure dependencies are installed (first time or after updates)
3. uv run scripts/ms-todo-sync.py lists # Test auth & see available lists
→ If fails with exit code 1 ("Not logged in"):
a. uv run scripts/ms-todo-sync.py login get # Get code
b. Present URL + code to user
c. Wait for user confirmation
d. uv run scripts/ms-todo-sync.py login verify
4. When adding tasks:
→ Analyze task context from user's description
→ Choose or create appropriate list name:
- Work-related → "Work" list
- Personal errands → "Personal" list
- Shopping items → "Shopping" list
- Project-specific → Use project name as list
→ Add task with appropriate list via `-l` option
5. Verify results (e.g., list tasks after adding)Example task categorization:
Note: If no list is specified, tasks are added to the user's default Microsoft To Do list.
complete and delete require exact title match.detail and search support partial/fuzzy keyword match (case-insensitive).search first to find the exact title, then use it in subsequent commands.When -l is not specified, the tool uses your Microsoft To Do default list (typically "Tasks"). To target a specific list, provide the -l option.
bash# Check existing lists first uv run scripts/ms-todo-sync.py lists # Add task to specific list (list auto-created if needed) uv run scripts/ms-todo-sync.py add "Report" -l "Work" -p high -d 3 -D "Q4 financials" # Add task to default list (no -l option) uv run scripts/ms-todo-sync.py add "Buy milk" # Add task with reminder in 2 hours uv run scripts/ms-todo-sync.py add "Call client" -r 2h # Add task with specific reminder date and time uv run scripts/ms-todo-sync.py add "Meeting" -d 2026-03-15 -r "2026-03-15 14:30" # Add recurring tasks uv run scripts/ms-todo-sync.py add "Daily standup" -l "Work" -R daily -d 7 uv run scripts/ms-todo-sync.py add "Weekly review" -R weekly -d 2026-02-17 uv run scripts/ms-todo-sync.py add "Gym" -R weekdays -l "Personal" uv run scripts/ms-todo-sync.py add "Monthly report" -R monthly -p high -d 30 # Search then complete (use exact title from search results) uv run scripts/ms-todo-sync.py search "report" uv run scripts/ms-todo-sync.py complete "Report" -l "Work" # Delete (use -y only when user intent is clear) uv run scripts/ms-todo-sync.py delete "Old task" -y # Views uv run scripts/ms-todo-sync.py -v pending -g # all pending, grouped uv run scripts/ms-todo-sync.py -v detail "report" # task detail with fuzzy match uv run scripts/ms-todo-sync.py export -o "backup.json" # export all
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→fail | 7,222 | 7,052 | -2% | 1 | 1 | 0% | 1,274 | 4,763 | +274% | 0 | 0 | — |
case-02 | fail→fail | 5,660 | 6,169 | +9% | 1 | 1 | 0% | 515 | 4,700 | +813% | 0 | 0 | — |
case-03 | fail→fail | 8,553 | 6,343 | -26% | 1 | 1 | 0% | 1,672 | 4,693 | +181% | 0 | 0 | — |
case-04 | fail→fail | 6,564 | 4,199 | -36% | 1 | 1 | 0% | 970 | 4,565 | +371% | 0 | 0 | — |
case-05 | fail→pass | 12,579 | 2,405 | -81% | 1 | 1 | 0% | 2,184 | 4,737 | +117% | 0 | 0 | — |
case-06 | fail→pass | 8,924 | 2,308 | -74% | 1 | 1 | 0% | 1,617 | 4,657 | +188% | 0 | 0 | — |
case-07 | fail→pass | 6,668 | 3,515 | -47% | 1 | 1 | 0% | 1,092 | 4,610 | +322% | 0 | 0 | — |
case-08 | fail→pass | 10,203 | 2,445 | -76% | 1 | 1 | 0% | 1,774 | 4,684 | +164% | 0 | 0 | — |
case-09 | fail→fail | 6,243 | 5,582 | -11% | 1 | 1 | 0% | 1,061 | 4,551 | +329% | 0 | 0 | — |
case-10 | fail→pass | 11,547 | 5,411 | -53% | 1 | 1 | 0% | 1,931 | 4,630 | +140% | 0 | 0 | — |
case-11 | fail→fail | 7,454 | 5,899 | -21% | 1 | 1 | 0% | 1,141 | 4,704 | +312% | 0 | 0 | — |
case-12 | fail→fail | 4,663 | 5,831 | +25% | 1 | 1 | 0% | 622 | 4,680 | +652% | 0 | 0 | — |
case-13 | fail→fail | 2,204 | 6,435 | +192% | 1 | 1 | 0% | 325 | 4,702 | +1347% | 0 | 0 | — |
case-14 | fail→pass | 7,510 | 1,541 | -79% | 1 | 1 | 0% | 1,332 | 4,555 | +242% | 0 | 0 | — |
case-15 | fail→fail | 7,642 | 5,253 | -31% | 1 | 1 | 0% | 1,453 | 4,619 | +218% | 0 | 0 | — |
case-16 | fail→fail | 4,083 | 5,266 | +29% | 1 | 1 | 0% | 552 | 4,663 | +745% | 0 | 0 | — |
case-17 | fail→fail | 4,884 | 5,935 | +22% | 1 | 1 | 0% | 915 | 4,702 | +414% | 0 | 0 | — |
case-18 | fail→fail | 12,862 | 5,811 | -55% | 1 | 1 | 0% | 2,329 | 4,638 | +99% | 0 | 0 | — |
case-19 | fail→fail | 12,275 | 4,615 | -62% | 1 | 1 | 0% | 2,173 | 4,554 | +110% | 0 | 0 | — |
case-20 | pass→pass | 7,899 | 8,102 | +3% | 1 | 1 | 0% | 1,697 | 6,151 | +262% | 0 | 0 | — |
case-21 | pass→pass | 12,963 | 10,230 | -21% | 1 | 1 | 0% | 2,298 | 6,178 | +169% | 0 | 0 | — |
case-22 | pass→pass | 8,353 | 5,278 | -37% | 1 | 1 | 0% | 1,540 | 5,506 | +258% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted, and 9 counted toward the lift figure. The other 13 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of +27 percentage points is the difference between those two pass rates over the 9 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.