✓ Verified 💻 Development ✓ Enhanced Data

Ms Todo Oauth

A robust CLI skill to manage Microsoft To Do tasks via Microsoft Graph API.

Rating
4.1 (171 reviews)
Downloads
17,120 downloads
Version
1.0.0

Overview

A robust CLI skill to manage Microsoft To Do tasks via Microsoft Graph API.

Complete Documentation

View Source →

ms-todo-oauth

A fully-tested Microsoft To Do command-line client for managing tasks and lists via Microsoft Graph API.

⚠️This is a oauth based script. It contains a generated Azure Client ID and Secret ID

IF YOU WORRIED ABOUT YOUR PRIVACY, CONSIDER REPLACING THEM TO YOUR OWN IN scripts\ms-todo-oauth.py. Just search for values below:

client_id="ca6ec244……

client_secret="TwQ8Q……

✨ Features

  • Full Task Management: Create, complete, delete, and search tasks
  • 🗂️ List Organization: Create and manage multiple task lists
  • Rich Task Options: Priorities, due dates, reminders, descriptions, tags
  • 🔄 Recurring Tasks: Daily, weekly, monthly patterns with custom intervals
  • 📊 Multiple Views: Today, overdue, pending, statistics
  • 🔍 Powerful Search: Find tasks across all lists
  • 💾 Data Export: Export all tasks to JSON
  • 🧪 Fully Tested: 29 comprehensive automated tests
  • 🌐 Unicode Support: Full support for Chinese characters and emojis

Prerequisites

  • Python >= 3.9 must be installed
  • Working directory: All commands MUST be run from the root of this skill (the directory containing this SKILL.md file)
  • Network access: Requires internet access to Microsoft Graph API endpoints
  • Microsoft Account: Personal Microsoft account (Hotmail, Outlook.com) or work/school account
  • Authentication: First-time use requires OAuth2 login via browser. See Authentication section
  • Token cache: ~/.mstodo_token_cache.json (persists across sessions, auto-refreshed)

Installation & Setup

First-Time Setup

Before using this skill for the first time, dependencies must be installed:

bash
# Navigate to skill directory
cd <path-to-ms-todo-oauth>

# Create a venv in the project (creates '.venv' folder)
python3 -m venv .venv
# Activate the venv choose based on platforms:
#- Bash/Zsh: 
source .venv/bin/activate
# - Fish: 
source .venv/bin/activate.fish
#  - Windows (PowerShell):
.venv\Scripts\Activate.ps1

pip install --upgrade pip
pip install -r requirements.txt

# Alternative (global python env, not recommended):
# pip install -r requirements.txt

Dependencies:

  • msal (Microsoft Authentication Library) - Official Microsoft OAuth library
  • requests - HTTP client for API calls
  • Specified in requirements.txt

Environment Verification

After installation, verify the setup:

bash
# If using native venv (activate as above):
python3 scripts/ms-todo-oauth.py --help

# Expected: Command help text should be displayed

Troubleshooting:

  • If Python not found, install Python 3.9 or higher from https://python.org

Testing (Optional but Recommended)

Verify all functionality works correctly:

bash
# Run comprehensive automated test suite (29 tests)
python3 test_ms_todo_oauth.py

# Expected: All tests pass (100% pass rate)

See Testing section for details.

Security Notes

  • Uses official Microsoft Graph API via Microsoft's msal library
  • All code is plain Python (.py files), readable and auditable
  • Tokens stored locally in ~/.mstodo_token_cache.json
  • All API calls go directly to Microsoft endpoints (graph.microsoft.com)
  • OAuth2 standard authentication flow
  • No third-party services involved

Command Reference

All commands follow this pattern:

text
python3 scripts/ms-todo-oauth.py [GLOBAL_OPTIONS] <command> [COMMAND_OPTIONS]

Global Options

OptionDescription
-v, --verboseShow detailed information (IDs, dates, notes).Must be placed BEFORE the subcommand.
--debugEnable debug mode to display API requests and responses. Useful for troubleshooting.Must be placed BEFORE the subcommand.
--reauthForce re-authentication by clearing the token cache and starting fresh login
⚠️ Common mistake: Global options MUST come before the subcommand.
> - ✅ python3 scripts/ms-todo-oauth.py -v lists
- ✅ python3 scripts/ms-todo-oauth.py --debug add "Task"
- ❌ python3 scripts/ms-todo-oauth.py lists -v


Authentication

Authentication uses OAuth2 authorization code flow, designed for both interactive and automated environments.

#### login get — Get OAuth2 authorization URL

bash
python3 scripts/ms-todo-oauth.py login get

Output example:

text
======================================================================
🔐 OAuth2 Authorization Required
======================================================================

Please visit the following URL to authorize the application:

  https://login.microsoftonline.com/consumers/oauth2/v2.0/authorize?...

After authorization, you will be redirected to a callback URL.
Copy the 'code' parameter from the callback URL and run:

  ms-todo-oauth.py login verify <authorization_code>

======================================================================

What to do:

  • Open the provided URL in your browser
  • Sign in with your Microsoft account
  • Grant permissions when prompted
  • You'll be redirected to a URL like: http://localhost:8000/callback?code=M.R3_BAY.abc123...
  • Copy the entire code after code= (usually a long string starting with M.R3_BAY.)
Agent behavior: Present the URL to the user and explain they need to:
  • Visit the URL
  • Complete the login
  • Copy the authorization code from the callback URL
  • Provide it to you
#### login verify — Complete login with authorization code

bash
python3 scripts/ms-todo-oauth.py login verify <authorization_code>

Example:

bash
python3 scripts/ms-todo-oauth.py login verify "M.R3_BAY.abc123def456..."

Output on success:

text
✓ Authentication successful!
✓ Login information saved, you will be logged in automatically next time.

Output on failure:

text
❌ Token acquisition failed
Error: invalid_grant
Description: AADSTS54005: OAuth2 Authorization code was already redeemed...

Exit code: 0 on success, 1 on failure.

Important notes:

  • Each authorization code can only be used ONCE
  • If verification fails, you need to run login get again to get a new code
  • Once successfully logged in, the token is cached and you won't need to login again unless:
  • You run logout
  • You run --reauth
  • The token expires and cannot be auto-refreshed
#### logout — Clear saved login

bash
python3 scripts/ms-todo-oauth.py logout

Output: ✓ Login information cleared

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.


List Management

#### lists — List all task lists

bash
python3 scripts/ms-todo-oauth.py lists
python3 scripts/ms-todo-oauth.py -v lists  # with IDs and creation dates

Output example:

text
📋 Task Lists (3 total):

1. 任务
   ID: AQMkADAwATYwMAItYTQwZC04OThhLTAwAi0wMAoALgAAA0QJKpxW32BIsIlHaM...
   Created: 2024-12-15T08:30:00Z
2. Work
3. Shopping

#### create-list — Create a new list

bash
python3 scripts/ms-todo-oauth.py create-list "<name>"

ArgumentRequiredDescription
nameYesName of the new list (supports Unicode/Chinese)
Example:

bash
python3 scripts/ms-todo-oauth.py create-list "项目 A"

Output: ✓ List created: 项目 A

#### delete-list — Delete a list

bash
python3 scripts/ms-todo-oauth.py delete-list "<name>" [-y]

Argument/OptionRequiredDescription
nameYesName of the list to delete
-y, --yesNoSkip confirmation prompt
⚠️ This is a destructive operation. Without -y, the command will prompt for confirmation. All tasks in the list will be deleted. Consider asking the user before deleting important lists.

Output: ✓ List deleted:

Exit code: 1 if list not found, 0 on success


Task Operations

#### add — Add a new task

bash
python3 scripts/ms-todo-oauth.py add "<title>" [options]

OptionRequiredDefaultDescription
titleYesTask title (positional argument, supports Unicode/Chinese/emojis)
-l, --listNo(default list)Target list name. If not specified, uses your Microsoft To Do default list.
-p, --priorityNonormalPriority:low, normal, high
-d, --dueNoDue date. Accepts days from now (3 or 3d) or date (2026-02-15). Note: Only date is supported by Microsoft To Do API, not time.
-r, --reminderNoReminder datetime. Formats:3h (hours from now), 2d (days from now), 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, --recurrenceNoRecurrence 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).
-D, --descriptionNoTask description/notes (supports multiline with quotes)
-t, --tagsNoComma-separated tags/categories (e.g.,"work,urgent")
--create-listNoFalseCreate the list if it doesn't exist (deprecated, lists auto-create now)
Auto-created lists: If the specified list doesn't exist, it will be automatically created.

Output example:

text
✓ Task added: Complete report

With recurrence:

text
✓ Task added: Daily standup
🔄 Recurring task created

Examples:

bash
# Simple task
python3 scripts/ms-todo-oauth.py add "Buy milk" -l "Shopping"

# High priority task due in 3 days
python3 scripts/ms-todo-oauth.py add "Submit report" -l "Work" -p high -d 3

# Task with reminder in 2 hours
python3 scripts/ms-todo-oauth.py add "Call client" -r 2h

# Task with specific date and time reminder
python3 scripts/ms-todo-oauth.py add "Meeting" -d 2026-03-15 -r "2026-03-15 14:30"

# Daily recurring task
python3 scripts/ms-todo-oauth.py add "Daily standup" -l "Work" -R daily

# Weekday recurring task  
python3 scripts/ms-todo-oauth.py add "Gym" -R weekdays -l "Personal"

# Task with all options
python3 scripts/ms-todo-oauth.py add "Project Review" \
  -l "Work" \
  -p high \
  -d 7 \
  -r "2026-02-20 14:00" \
  -D "Review Q1 deliverables and prepare presentation" \
  -t "work,important,meeting"

# Chinese task with emoji
python3 scripts/ms-todo-oauth.py add "🎉 完成项目" -l "任务" -p high

#### complete — Mark a task as completed

bash
python3 scripts/ms-todo-oauth.py complete "<title>" [-l "<list>"]

OptionRequiredDefaultDescription
titleYesExact task title
-l, --listNo(default list)List name where the task resides
Title matching: Requires exact match. If unsure of exact title, use search first.

Output: ✓ Task completed: </code></p><p class="my-4 text-gray-700 leading-relaxed"><strong class="font-semibold">Exit code</strong>: 1 if task not found, 0 on success</p><p class="my-4 text-gray-700 leading-relaxed">#### <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">delete</code> — Delete a task</p><p class="my-4 text-gray-700 leading-relaxed"><div class="relative group my-6"> <div class="absolute top-2 right-2 px-2 py-1 text-xs font-medium text-gray-400 bg-gray-800 rounded">bash</div> <pre class="bg-gray-900 text-gray-100 p-4 rounded-lg overflow-x-auto text-sm leading-relaxed"><code class="language-bash">python3 scripts/ms-todo-oauth.py delete "<title>" [-l "<list>"] [-y]</code></pre> </div></p><p class="my-4 text-gray-700 leading-relaxed"><table class="w-full my-6 border-collapse"><thead><tr><th class="bg-gray-100 px-4 py-2 text-left text-sm font-semibold text-gray-900 border-b-2 border-gray-300">Option</th><th class="bg-gray-100 px-4 py-2 text-left text-sm font-semibold text-gray-900 border-b-2 border-gray-300">Required</th><th class="bg-gray-100 px-4 py-2 text-left text-sm font-semibold text-gray-900 border-b-2 border-gray-300">Default</th><th class="bg-gray-100 px-4 py-2 text-left text-sm font-semibold text-gray-900 border-b-2 border-gray-300">Description</th></tr></thead><tbody><tr class="border-b border-gray-200 hover:bg-gray-50"><td class="px-4 py-2 text-sm text-gray-700">title</td><td class="px-4 py-2 text-sm text-gray-700">Yes</td><td class="px-4 py-2 text-sm text-gray-700">—</td><td class="px-4 py-2 text-sm text-gray-700"><strong class="font-semibold">Exact</strong> task title</td></tr><tr class="border-b border-gray-200 hover:bg-gray-50"><td class="px-4 py-2 text-sm text-gray-700">-l, --list</td><td class="px-4 py-2 text-sm text-gray-700">No</td><td class="px-4 py-2 text-sm text-gray-700">(default list)</td><td class="px-4 py-2 text-sm text-gray-700">List name where the task resides</td></tr><tr class="border-b border-gray-200 hover:bg-gray-50"><td class="px-4 py-2 text-sm text-gray-700">-y, --yes</td><td class="px-4 py-2 text-sm text-gray-700">No</td><td class="px-4 py-2 text-sm text-gray-700">—</td><td class="px-4 py-2 text-sm text-gray-700">Skip confirmation prompt</td></tr></tbody></table> <blockquote class="border-l-4 border-primary-300 pl-4 py-2 my-4 text-gray-700 italic bg-primary-50 rounded-r">⚠️ <strong class="font-semibold">Destructive operation</strong>. Without <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">-y</code>, will prompt for confirmation.</blockquote></p><p class="my-4 text-gray-700 leading-relaxed">Output: <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">✓ Task deleted: <title></code></p><p class="my-4 text-gray-700 leading-relaxed"><strong class="font-semibold">Exit code</strong>: 1 if task not found, 0 on success</p><p class="my-4 text-gray-700 leading-relaxed"><hr class="my-8 border-t border-gray-300"></p><p class="my-4 text-gray-700 leading-relaxed"><h3 class="text-xl font-semibold text-gray-900 mt-8 mb-4">Task Views</h3></p><p class="my-4 text-gray-700 leading-relaxed">#### <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">tasks</code> — List tasks in a specific list</p><p class="my-4 text-gray-700 leading-relaxed"><div class="relative group my-6"> <div class="absolute top-2 right-2 px-2 py-1 text-xs font-medium text-gray-400 bg-gray-800 rounded">bash</div> <pre class="bg-gray-900 text-gray-100 p-4 rounded-lg overflow-x-auto text-sm leading-relaxed"><code class="language-bash">python3 scripts/ms-todo-oauth.py tasks "<list>" [-a]</code></pre> </div></p><p class="my-4 text-gray-700 leading-relaxed"><table class="w-full my-6 border-collapse"><thead><tr><th class="bg-gray-100 px-4 py-2 text-left text-sm font-semibold text-gray-900 border-b-2 border-gray-300">Option</th><th class="bg-gray-100 px-4 py-2 text-left text-sm font-semibold text-gray-900 border-b-2 border-gray-300">Required</th><th class="bg-gray-100 px-4 py-2 text-left text-sm font-semibold text-gray-900 border-b-2 border-gray-300">Description</th></tr></thead><tbody><tr class="border-b border-gray-200 hover:bg-gray-50"><td class="px-4 py-2 text-sm text-gray-700">list</td><td class="px-4 py-2 text-sm text-gray-700">Yes</td><td class="px-4 py-2 text-sm text-gray-700">List name (exact match)</td></tr><tr class="border-b border-gray-200 hover:bg-gray-50"><td class="px-4 py-2 text-sm text-gray-700">-a, --all</td><td class="px-4 py-2 text-sm text-gray-700">No</td><td class="px-4 py-2 text-sm text-gray-700">Include completed tasks (default: incomplete only)</td></tr></tbody></table> <strong class="font-semibold">Output example:</strong></p><p class="my-4 text-gray-700 leading-relaxed"><div class="relative group my-6"> <div class="absolute top-2 right-2 px-2 py-1 text-xs font-medium text-gray-400 bg-gray-800 rounded">text</div> <pre class="bg-gray-900 text-gray-100 p-4 rounded-lg overflow-x-auto text-sm leading-relaxed"><code class="language-text">📋 Tasks in list "Work" (2 total): 1. [In Progress] Write documentation ⭐ 2. [In Progress] Review PR</code></pre> </div></p><p class="my-4 text-gray-700 leading-relaxed"><strong class="font-semibold">With <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">-a</code> flag:</strong></p><p class="my-4 text-gray-700 leading-relaxed"><div class="relative group my-6"> <div class="absolute top-2 right-2 px-2 py-1 text-xs font-medium text-gray-400 bg-gray-800 rounded">text</div> <pre class="bg-gray-900 text-gray-100 p-4 rounded-lg overflow-x-auto text-sm leading-relaxed"><code class="language-text">📋 Tasks in list "Work" (3 total): 1. [In Progress] Write documentation ⭐ 2. [Completed] Submit report 3. [In Progress] Review PR</code></pre> </div></p><p class="my-4 text-gray-700 leading-relaxed"><strong class="font-semibold">Exit code</strong>: 1 if list not found, 0 on success</p><p class="my-4 text-gray-700 leading-relaxed">#### <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">pending</code> — All incomplete tasks across all lists</p><p class="my-4 text-gray-700 leading-relaxed"><div class="relative group my-6"> <div class="absolute top-2 right-2 px-2 py-1 text-xs font-medium text-gray-400 bg-gray-800 rounded">bash</div> <pre class="bg-gray-900 text-gray-100 p-4 rounded-lg overflow-x-auto text-sm leading-relaxed"><code class="language-bash">python3 scripts/ms-todo-oauth.py pending [-g]</code></pre> </div></p><p class="my-4 text-gray-700 leading-relaxed"><table class="w-full my-6 border-collapse"><thead><tr><th class="bg-gray-100 px-4 py-2 text-left text-sm font-semibold text-gray-900 border-b-2 border-gray-300">Option</th><th class="bg-gray-100 px-4 py-2 text-left text-sm font-semibold text-gray-900 border-b-2 border-gray-300">Required</th><th class="bg-gray-100 px-4 py-2 text-left text-sm font-semibold text-gray-900 border-b-2 border-gray-300">Description</th></tr></thead><tbody><tr class="border-b border-gray-200 hover:bg-gray-50"><td class="px-4 py-2 text-sm text-gray-700">-g, --group</td><td class="px-4 py-2 text-sm text-gray-700">No</td><td class="px-4 py-2 text-sm text-gray-700">Group results by list</td></tr></tbody></table> <strong class="font-semibold">Output example (with <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">-g</code>):</strong></p><p class="my-4 text-gray-700 leading-relaxed"><div class="relative group my-6"> <div class="absolute top-2 right-2 px-2 py-1 text-xs font-medium text-gray-400 bg-gray-800 rounded">text</div> <pre class="bg-gray-900 text-gray-100 p-4 rounded-lg overflow-x-auto text-sm leading-relaxed"><code class="language-text">📋 All incomplete tasks (3 total): 📂 Work: [In Progress] Write documentation ⭐ [In Progress] Review PR 📂 Shopping: [In Progress] Buy groceries</code></pre> </div></p><p class="my-4 text-gray-700 leading-relaxed"><strong class="font-semibold">Without <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">-g</code>:</strong></p><p class="my-4 text-gray-700 leading-relaxed"><div class="relative group my-6"> <div class="absolute top-2 right-2 px-2 py-1 text-xs font-medium text-gray-400 bg-gray-800 rounded">text</div> <pre class="bg-gray-900 text-gray-100 p-4 rounded-lg overflow-x-auto text-sm leading-relaxed"><code class="language-text">📋 All incomplete tasks (3 total): [In Progress] Write documentation ⭐ List: Work [In Progress] Review PR List: Work [In Progress] Buy groceries List: Shopping</code></pre> </div></p><p class="my-4 text-gray-700 leading-relaxed">#### <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">today</code> — Tasks due today</p><p class="my-4 text-gray-700 leading-relaxed"><div class="relative group my-6"> <div class="absolute top-2 right-2 px-2 py-1 text-xs font-medium text-gray-400 bg-gray-800 rounded">bash</div> <pre class="bg-gray-900 text-gray-100 p-4 rounded-lg overflow-x-auto text-sm leading-relaxed"><code class="language-bash">python3 scripts/ms-todo-oauth.py today</code></pre> </div></p><p class="my-4 text-gray-700 leading-relaxed">Lists incomplete tasks with due date matching today's date.</p><p class="my-4 text-gray-700 leading-relaxed"><strong class="font-semibold">Output example:</strong></p><p class="my-4 text-gray-700 leading-relaxed"><div class="relative group my-6"> <div class="absolute top-2 right-2 px-2 py-1 text-xs font-medium text-gray-400 bg-gray-800 rounded">text</div> <pre class="bg-gray-900 text-gray-100 p-4 rounded-lg overflow-x-auto text-sm leading-relaxed"><code class="language-text">📅 Tasks due today (2 total): [In Progress] Submit report ⭐ List: Work [In Progress] Buy groceries List: Shopping</code></pre> </div></p><p class="my-4 text-gray-700 leading-relaxed">If no tasks: <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">📅 No tasks due today</code></p><p class="my-4 text-gray-700 leading-relaxed">#### <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">overdue</code> — Overdue tasks</p><p class="my-4 text-gray-700 leading-relaxed"><div class="relative group my-6"> <div class="absolute top-2 right-2 px-2 py-1 text-xs font-medium text-gray-400 bg-gray-800 rounded">bash</div> <pre class="bg-gray-900 text-gray-100 p-4 rounded-lg overflow-x-auto text-sm leading-relaxed"><code class="language-bash">python3 scripts/ms-todo-oauth.py overdue</code></pre> </div></p><p class="my-4 text-gray-700 leading-relaxed">Lists incomplete tasks past their due date, sorted by days overdue.</p><p class="my-4 text-gray-700 leading-relaxed"><strong class="font-semibold">Output example:</strong></p><p class="my-4 text-gray-700 leading-relaxed"><div class="relative group my-6"> <div class="absolute top-2 right-2 px-2 py-1 text-xs font-medium text-gray-400 bg-gray-800 rounded">text</div> <pre class="bg-gray-900 text-gray-100 p-4 rounded-lg overflow-x-auto text-sm leading-relaxed"><code class="language-text">⚠️ Overdue tasks (1 total): [In Progress] Submit report ⭐ List: Work Overdue: 3 days</code></pre> </div></p><p class="my-4 text-gray-700 leading-relaxed">If no overdue tasks: <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">✓ No overdue tasks</code></p><p class="my-4 text-gray-700 leading-relaxed">#### <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">detail</code> — View full task details</p><p class="my-4 text-gray-700 leading-relaxed"><div class="relative group my-6"> <div class="absolute top-2 right-2 px-2 py-1 text-xs font-medium text-gray-400 bg-gray-800 rounded">bash</div> <pre class="bg-gray-900 text-gray-100 p-4 rounded-lg overflow-x-auto text-sm leading-relaxed"><code class="language-bash">python3 scripts/ms-todo-oauth.py detail "<title>" [-l "<list>"]</code></pre> </div></p><p class="my-4 text-gray-700 leading-relaxed"><table class="w-full my-6 border-collapse"><thead><tr><th class="bg-gray-100 px-4 py-2 text-left text-sm font-semibold text-gray-900 border-b-2 border-gray-300">Option</th><th class="bg-gray-100 px-4 py-2 text-left text-sm font-semibold text-gray-900 border-b-2 border-gray-300">Required</th><th class="bg-gray-100 px-4 py-2 text-left text-sm font-semibold text-gray-900 border-b-2 border-gray-300">Default</th><th class="bg-gray-100 px-4 py-2 text-left text-sm font-semibold text-gray-900 border-b-2 border-gray-300">Description</th></tr></thead><tbody><tr class="border-b border-gray-200 hover:bg-gray-50"><td class="px-4 py-2 text-sm text-gray-700">title</td><td class="px-4 py-2 text-sm text-gray-700">Yes</td><td class="px-4 py-2 text-sm text-gray-700">—</td><td class="px-4 py-2 text-sm text-gray-700">Task title (supports<strong class="font-semibold">partial/fuzzy match</strong>)</td></tr><tr class="border-b border-gray-200 hover:bg-gray-50"><td class="px-4 py-2 text-sm text-gray-700">-l, --list</td><td class="px-4 py-2 text-sm text-gray-700">No</td><td class="px-4 py-2 text-sm text-gray-700">(default list)</td><td class="px-4 py-2 text-sm text-gray-700">List name</td></tr></tbody></table> <strong class="font-semibold">Fuzzy matching</strong>: Matches tasks containing the search string (case-insensitive).</p><p class="my-4 text-gray-700 leading-relaxed">When multiple tasks match: <ul class="my-4 space-y-2"><li class="ml-6 mb-2 text-gray-700 list-disc">Prefers <strong class="font-semibold">incomplete</strong> tasks over completed</li> <li class="ml-6 mb-2 text-gray-700 list-disc">Returns most recently modified task</li> </ul> <strong class="font-semibold">Output example:</strong></p><p class="my-4 text-gray-700 leading-relaxed"><div class="relative group my-6"> <div class="absolute top-2 right-2 px-2 py-1 text-xs font-medium text-gray-400 bg-gray-800 rounded">text</div> <pre class="bg-gray-900 text-gray-100 p-4 rounded-lg overflow-x-auto text-sm leading-relaxed"><code class="language-text">============================================================ 📌 Task Details ============================================================ 📋 Title: Complete Q1 Report 🔖 Status: [In Progress] ⚡ Priority: ⭐ High 📅 Created: 2026-01-15 08:30:00 📝 Modified: 2026-02-10 14:22:00 ⏰ Due: 2026-02-20 00:00:00 🔔 Reminder: 2026-02-20 09:00:00 📝 Notes: - Review sales figures - Include charts - Prepare for board meeting 🏷️ Categories: work, important, Q1 🔄 Recurrence: Every week on Monday Start date: 2026-02-17 No end date ============================================================</code></pre> </div></p><p class="my-4 text-gray-700 leading-relaxed">#### <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">search</code> — Search tasks by keyword</p><p class="my-4 text-gray-700 leading-relaxed"><div class="relative group my-6"> <div class="absolute top-2 right-2 px-2 py-1 text-xs font-medium text-gray-400 bg-gray-800 rounded">bash</div> <pre class="bg-gray-900 text-gray-100 p-4 rounded-lg overflow-x-auto text-sm leading-relaxed"><code class="language-bash">python3 scripts/ms-todo-oauth.py search "<keyword>"</code></pre> </div></p><p class="my-4 text-gray-700 leading-relaxed">Searches across <strong class="font-semibold">all lists</strong> in both task titles and descriptions (case-insensitive).</p><p class="my-4 text-gray-700 leading-relaxed"><strong class="font-semibold">Output example:</strong></p><p class="my-4 text-gray-700 leading-relaxed"><div class="relative group my-6"> <div class="absolute top-2 right-2 px-2 py-1 text-xs font-medium text-gray-400 bg-gray-800 rounded">text</div> <pre class="bg-gray-900 text-gray-100 p-4 rounded-lg overflow-x-auto text-sm leading-relaxed"><code class="language-text">🔍 Search results for "report" (2 found): [In Progress] Complete Q1 Report ⭐ List: Work Notes: Review sales figures... [Completed] Submit weekly report List: Work</code></pre> </div></p><p class="my-4 text-gray-700 leading-relaxed">#### <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">stats</code> — Task statistics</p><p class="my-4 text-gray-700 leading-relaxed"><div class="relative group my-6"> <div class="absolute top-2 right-2 px-2 py-1 text-xs font-medium text-gray-400 bg-gray-800 rounded">bash</div> <pre class="bg-gray-900 text-gray-100 p-4 rounded-lg overflow-x-auto text-sm leading-relaxed"><code class="language-bash">python3 scripts/ms-todo-oauth.py stats</code></pre> </div></p><p class="my-4 text-gray-700 leading-relaxed">Shows aggregate statistics across all lists.</p><p class="my-4 text-gray-700 leading-relaxed"><strong class="font-semibold">Output example:</strong></p><p class="my-4 text-gray-700 leading-relaxed"><div class="relative group my-6"> <div class="absolute top-2 right-2 px-2 py-1 text-xs font-medium text-gray-400 bg-gray-800 rounded">text</div> <pre class="bg-gray-900 text-gray-100 p-4 rounded-lg overflow-x-auto text-sm leading-relaxed"><code class="language-text">📊 Task Statistics: Total lists: 3 Total tasks: 15 Completed: 10 Pending: 5 High priority: 2 Overdue: 1 Completion rate: 66.7%</code></pre> </div></p><p class="my-4 text-gray-700 leading-relaxed">#### <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">export</code> — Export all tasks to JSON</p><p class="my-4 text-gray-700 leading-relaxed"><div class="relative group my-6"> <div class="absolute top-2 right-2 px-2 py-1 text-xs font-medium text-gray-400 bg-gray-800 rounded">bash</div> <pre class="bg-gray-900 text-gray-100 p-4 rounded-lg overflow-x-auto text-sm leading-relaxed"><code class="language-bash">python3 scripts/ms-todo-oauth.py export [-o "<filename>"]</code></pre> </div></p><p class="my-4 text-gray-700 leading-relaxed"><table class="w-full my-6 border-collapse"><thead><tr><th class="bg-gray-100 px-4 py-2 text-left text-sm font-semibold text-gray-900 border-b-2 border-gray-300">Option</th><th class="bg-gray-100 px-4 py-2 text-left text-sm font-semibold text-gray-900 border-b-2 border-gray-300">Required</th><th class="bg-gray-100 px-4 py-2 text-left text-sm font-semibold text-gray-900 border-b-2 border-gray-300">Default</th><th class="bg-gray-100 px-4 py-2 text-left text-sm font-semibold text-gray-900 border-b-2 border-gray-300">Description</th></tr></thead><tbody><tr class="border-b border-gray-200 hover:bg-gray-50"><td class="px-4 py-2 text-sm text-gray-700">-o, --output</td><td class="px-4 py-2 text-sm text-gray-700">No</td><td class="px-4 py-2 text-sm text-gray-700">todo_export.json</td><td class="px-4 py-2 text-sm text-gray-700">Output file path</td></tr></tbody></table> Exports complete task data from all lists in JSON format.</p><p class="my-4 text-gray-700 leading-relaxed"><strong class="font-semibold">Output:</strong> <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">✓ Tasks exported to: <filename></code></p><p class="my-4 text-gray-700 leading-relaxed"><strong class="font-semibold">JSON structure:</strong></p><p class="my-4 text-gray-700 leading-relaxed"><div class="relative group my-6"> <div class="absolute top-2 right-2 px-2 py-1 text-xs font-medium text-gray-400 bg-gray-800 rounded">json</div> <pre class="bg-gray-900 text-gray-100 p-4 rounded-lg overflow-x-auto text-sm leading-relaxed"><code class="language-json">{ "Work": [ { "id": "AQMkADAwATYwMAItYTQw...", "title": "Complete report", "status": "notStarted", "importance": "high", "createdDateTime": "2026-01-15T08:30:00Z", "dueDateTime": { "dateTime": "2026-02-20T00:00:00.0000000", "timeZone": "UTC" }, "body": { "content": "Review Q1 numbers", "contentType": "text" }, "categories": ["work", "important"] } ], "Shopping": [...] }</code></pre> </div></p><p class="my-4 text-gray-700 leading-relaxed"><hr class="my-8 border-t border-gray-300"></p><p class="my-4 text-gray-700 leading-relaxed"><h2 class="text-2xl font-bold text-gray-900 mt-10 mb-6 border-b border-gray-200 pb-2">Error Handling</h2></p><p class="my-4 text-gray-700 leading-relaxed"><h3 class="text-xl font-semibold text-gray-900 mt-8 mb-4">Exit Codes</h3></p><p class="my-4 text-gray-700 leading-relaxed"><table class="w-full my-6 border-collapse"><thead><tr><th class="bg-gray-100 px-4 py-2 text-left text-sm font-semibold text-gray-900 border-b-2 border-gray-300">Code</th><th class="bg-gray-100 px-4 py-2 text-left text-sm font-semibold text-gray-900 border-b-2 border-gray-300">Meaning</th></tr></thead><tbody><tr class="border-b border-gray-200 hover:bg-gray-50"><td class="px-4 py-2 text-sm text-gray-700">0</td><td class="px-4 py-2 text-sm text-gray-700">Success</td></tr><tr class="border-b border-gray-200 hover:bg-gray-50"><td class="px-4 py-2 text-sm text-gray-700">1</td><td class="px-4 py-2 text-sm text-gray-700">Failure (not logged in, API error, invalid arguments, resource not found)</td></tr><tr class="border-b border-gray-200 hover:bg-gray-50"><td class="px-4 py-2 text-sm text-gray-700">2</td><td class="px-4 py-2 text-sm text-gray-700">Invalid command-line arguments</td></tr></tbody></table> <h3 class="text-xl font-semibold text-gray-900 mt-8 mb-4">Common Error Messages</h3></p><p class="my-4 text-gray-700 leading-relaxed"><table class="w-full my-6 border-collapse"><thead><tr><th class="bg-gray-100 px-4 py-2 text-left text-sm font-semibold text-gray-900 border-b-2 border-gray-300">Error</th><th class="bg-gray-100 px-4 py-2 text-left text-sm font-semibold text-gray-900 border-b-2 border-gray-300">Cause</th><th class="bg-gray-100 px-4 py-2 text-left text-sm font-semibold text-gray-900 border-b-2 border-gray-300">Resolution</th></tr></thead><tbody><tr class="border-b border-gray-200 hover:bg-gray-50"><td class="px-4 py-2 text-sm text-gray-700">❌ Not logged in</td><td class="px-4 py-2 text-sm text-gray-700">No cached token or token expired</td><td class="px-4 py-2 text-sm text-gray-700">Run login get then login verify <code></td></tr><tr class="border-b border-gray-200 hover:bg-gray-50"><td class="px-4 py-2 text-sm text-gray-700">ModuleNotFoundError: No module named 'msal'</td><td class="px-4 py-2 text-sm text-gray-700">Dependencies not installed</td><td class="px-4 py-2 text-sm text-gray-700">Run pip install -r requirements.txt</td></tr><tr class="border-b border-gray-200 hover:bg-gray-50"><td class="px-4 py-2 text-sm text-gray-700">❌ List not found: <name></td><td class="px-4 py-2 text-sm text-gray-700">Specified list does not exist</td><td class="px-4 py-2 text-sm text-gray-700">Check list name with lists command. Note: exact match required.</td></tr><tr class="border-b border-gray-200 hover:bg-gray-50"><td class="px-4 py-2 text-sm text-gray-700">❌ Task not found: <name></td><td class="px-4 py-2 text-sm text-gray-700">No task with exact matching title</td><td class="px-4 py-2 text-sm text-gray-700">Use search to find exact title, or tasks "<list>" to list all tasks</td></tr><tr class="border-b border-gray-200 hover:bg-gray-50"><td class="px-4 py-2 text-sm text-gray-700">❌ Error: Invalid isoformat string</td><td class="px-4 py-2 text-sm text-gray-700">DateTime parsing error</td><td class="px-4 py-2 text-sm text-gray-700">This should not occur in v1.1.0+. If you see this, report as bug.</td></tr><tr class="border-b border-gray-200 hover:bg-gray-50"><td class="px-4 py-2 text-sm text-gray-700">❌ Error: Unsupported HTTP method</td><td class="px-4 py-2 text-sm text-gray-700">Internal API error</td><td class="px-4 py-2 text-sm text-gray-700">This should not occur in v1.1.0+. If you see this, report as bug.</td></tr><tr class="border-b border-gray-200 hover:bg-gray-50"><td class="px-4 py-2 text-sm text-gray-700">❌ Error: <API error message></td><td class="px-4 py-2 text-sm text-gray-700">Microsoft Graph API error</td><td class="px-4 py-2 text-sm text-gray-700">Retry; check network; use --debug for full details</td></tr><tr class="border-b border-gray-200 hover:bg-gray-50"><td class="px-4 py-2 text-sm text-gray-700">Network error / Connection timeout</td><td class="px-4 py-2 text-sm text-gray-700">No internet or API unreachable</td><td class="px-4 py-2 text-sm text-gray-700">Check network connection; verify access to graph.microsoft.com</td></tr></tbody></table> <hr class="my-8 border-t border-gray-300"></p><p class="my-4 text-gray-700 leading-relaxed"><h2 class="text-2xl font-bold text-gray-900 mt-10 mb-6 border-b border-gray-200 pb-2">Testing</h2></p><p class="my-4 text-gray-700 leading-relaxed">This skill includes a comprehensive test suite to ensure reliability.</p><p class="my-4 text-gray-700 leading-relaxed"><h3 class="text-xl font-semibold text-gray-900 mt-8 mb-4">Automated Testing</h3></p><p class="my-4 text-gray-700 leading-relaxed">Run the full test suite:</p><p class="my-4 text-gray-700 leading-relaxed"><div class="relative group my-6"> <div class="absolute top-2 right-2 px-2 py-1 text-xs font-medium text-gray-400 bg-gray-800 rounded">bash</div> <pre class="bg-gray-900 text-gray-100 p-4 rounded-lg overflow-x-auto text-sm leading-relaxed"><code class="language-bash">cd <skill-directory> python3 test_ms_todo_oauth.py</code></pre> </div></p><p class="my-4 text-gray-700 leading-relaxed"><strong class="font-semibold">Prerequisites:</strong> <ul class="my-4 space-y-2"><li class="ml-6 mb-2 text-gray-700 list-disc">Must be authenticated (logged in) before running tests</li> <li class="ml-6 mb-2 text-gray-700 list-disc">Internet connection required</li> <li class="ml-6 mb-2 text-gray-700 list-disc">Approximately 2-3 minutes to complete</li> </ul> <strong class="font-semibold">Test Coverage</strong> (29 tests): <ul class="my-4 space-y-2"><li class="ml-6 mb-2 text-gray-700 list-disc">✅ Authentication (login/logout)</li> <li class="ml-6 mb-2 text-gray-700 list-disc">✅ List management (create, delete, list)</li> <li class="ml-6 mb-2 text-gray-700 list-disc">✅ Basic task operations (add, complete, delete, list)</li> <li class="ml-6 mb-2 text-gray-700 list-disc">✅ Task options (priorities, due dates, reminders, descriptions, tags)</li> <li class="ml-6 mb-2 text-gray-700 list-disc">✅ Recurring tasks (daily, weekly, weekdays, monthly, custom intervals)</li> <li class="ml-6 mb-2 text-gray-700 list-disc">✅ Task views (today, overdue, pending, search, stats)</li> <li class="ml-6 mb-2 text-gray-700 list-disc">✅ Data export and validation</li> <li class="ml-6 mb-2 text-gray-700 list-disc">✅ Error handling (non-existent resources)</li> <li class="ml-6 mb-2 text-gray-700 list-disc">✅ Unicode support (Chinese characters, emojis)</li> </ul> <strong class="font-semibold">Expected output:</strong></p><p class="my-4 text-gray-700 leading-relaxed"><div class="relative group my-6"> <div class="absolute top-2 right-2 px-2 py-1 text-xs font-medium text-gray-400 bg-gray-800 rounded">text</div> <pre class="bg-gray-900 text-gray-100 p-4 rounded-lg overflow-x-auto text-sm leading-relaxed"><code class="language-text">======================================================================== TEST SUMMARY ======================================================================== Total tests: 29 Passed: 29 Failed: 0 Pass rate: 100.0% ======================================================================== 🎉 ALL TESTS PASSED! 🎉 ========================================================================</code></pre> </div></p><p class="my-4 text-gray-700 leading-relaxed"><h3 class="text-xl font-semibold text-gray-900 mt-8 mb-4">Manual Testing</h3></p><p class="my-4 text-gray-700 leading-relaxed">For manual verification, see <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">MANUAL_TEST_CHECKLIST.txt</code> which provides: <ul class="my-4 space-y-2"><li class="ml-6 mb-2 text-gray-700 list-disc">Step-by-step test procedures</li> <li class="ml-6 mb-2 text-gray-700 list-disc">Expected outcomes</li> <li class="ml-6 mb-2 text-gray-700 list-disc">9 test categories covering all functionality</li> </ul> <h3 class="text-xl font-semibold text-gray-900 mt-8 mb-4">Test Cleanup</h3></p><p class="my-4 text-gray-700 leading-relaxed">The automated test suite: <ul class="my-4 space-y-2"><li class="ml-6 mb-2 text-gray-700 list-disc">Creates a temporary test list (e.g., <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">🧪 Test List 14:23:45</code>)</li> <li class="ml-6 mb-2 text-gray-700 list-disc">Runs all tests in isolation</li> <li class="ml-6 mb-2 text-gray-700 list-disc">Deletes the test list on completion</li> <li class="ml-6 mb-2 text-gray-700 list-disc">Cleans up any temporary files</li> </ul> If tests are interrupted, you may need to manually delete leftover test lists.</p><p class="my-4 text-gray-700 leading-relaxed"><hr class="my-8 border-t border-gray-300"></p><p class="my-4 text-gray-700 leading-relaxed"><h2 class="text-2xl font-bold text-gray-900 mt-10 mb-6 border-b border-gray-200 pb-2">Agent Usage Guidelines</h2></p><p class="my-4 text-gray-700 leading-relaxed"><h3 class="text-xl font-semibold text-gray-900 mt-8 mb-4">Critical Rules</h3> <ul class="my-4 space-y-2"><li class="ml-6 mb-2 text-gray-700 list-decimal"><strong class="font-semibold">Working directory</strong>: Always <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">cd</code> to the directory containing this SKILL.md before running commands.</li> <li class="ml-6 mb-2 text-gray-700 list-decimal"><strong class="font-semibold">Dependency installation</strong>: Before first use or when encountering import errors, ensure all dependencies are installed.</li> <li class="ml-6 mb-2 text-gray-700 list-decimal"><strong class="font-semibold">Check authentication first</strong>: Before any operation, verify authentication status:</li> </ul> <div class="relative group my-6"> <div class="absolute top-2 right-2 px-2 py-1 text-xs font-medium text-gray-400 bg-gray-800 rounded">bash</div> <pre class="bg-gray-900 text-gray-100 p-4 rounded-lg overflow-x-auto text-sm leading-relaxed"><code class="language-bash">python3 scripts/ms-todo-oauth.py lists</code></pre> </div></p><p class="my-4 text-gray-700 leading-relaxed"> If this returns "Not logged in" error (exit code 1), initiate the login flow. <ul class="my-4 space-y-2"><li class="ml-6 mb-2 text-gray-700 list-decimal"><strong class="font-semibold">Task list organization</strong>: When adding tasks:</li> <li class="ml-6 mb-2 text-gray-700 list-disc">First, run <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">lists</code> to see available task lists</li> <li class="ml-6 mb-2 text-gray-700 list-disc">If user doesn't specify a list, tasks will be added to their <strong class="font-semibold">default list</strong> (usually "Tasks" or "任务")</li> <li class="ml-6 mb-2 text-gray-700 list-disc">Intelligently categorize tasks into appropriate lists:</li> <li class="ml-6 mb-2 text-gray-700 list-disc">Work tasks → "Work" list</li> <li class="ml-6 mb-2 text-gray-700 list-disc">Personal errands → "Personal" or default list</li> <li class="ml-6 mb-2 text-gray-700 list-disc">Shopping → "Shopping" list</li> <li class="ml-6 mb-2 text-gray-700 list-disc">Project-specific → Use project name as list</li> <li class="ml-6 mb-2 text-gray-700 list-disc">Lists will be auto-created if they don't exist</li> <li class="ml-6 mb-2 text-gray-700 list-disc">Support Chinese list names and Unicode characters</li> <li class="ml-6 mb-2 text-gray-700 list-decimal"><strong class="font-semibold">Destructive operations</strong>: For <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">delete</code> and <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">delete-list</code>:</li> <li class="ml-6 mb-2 text-gray-700 list-disc">These commands prompt for confirmation by default (blocking behavior)</li> <li class="ml-6 mb-2 text-gray-700 list-disc">Use <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">-y</code> flag ONLY when:</li> <li class="ml-6 mb-2 text-gray-700 list-disc">User has explicitly requested to delete without confirmation</li> <li class="ml-6 mb-2 text-gray-700 list-disc">The deletion intent is unambiguous and confirmed through conversation</li> <li class="ml-6 mb-2 text-gray-700 list-disc">When in doubt, ask the user for confirmation instead of using <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">-y</code></li> <li class="ml-6 mb-2 text-gray-700 list-disc">These operations return exit code 1 on failure (resource not found)</li> <li class="ml-6 mb-2 text-gray-700 list-decimal"><strong class="font-semibold">Global option placement</strong>: <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">-v</code>, <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">--debug</code>, and <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">--reauth</code> must come BEFORE the subcommand:</li> <li class="ml-6 mb-2 text-gray-700 list-disc">✅ <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">python3 scripts/ms-todo-oauth.py -v lists</code></li> <li class="ml-6 mb-2 text-gray-700 list-disc">❌ <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">python3 scripts/ms-todo-oauth.py lists -v</code></li> <li class="ml-6 mb-2 text-gray-700 list-decimal"><strong class="font-semibold">Login flow</strong>:</li> <li class="ml-6 mb-2 text-gray-700 list-disc">Do NOT call <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">login verify</code> until user confirms they've completed browser authentication</li> <li class="ml-6 mb-2 text-gray-700 list-disc">Each authorization code can only be used once</li> <li class="ml-6 mb-2 text-gray-700 list-disc">If verify fails, you must run <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">login get</code> again for a new code</li> <li class="ml-6 mb-2 text-gray-700 list-decimal"><strong class="font-semibold">Error handling</strong>:</li> <li class="ml-6 mb-2 text-gray-700 list-disc">Check exit codes: 0 = success, 1 = failure, 2 = invalid arguments</li> <li class="ml-6 mb-2 text-gray-700 list-disc">Parse error messages to provide helpful guidance</li> <li class="ml-6 mb-2 text-gray-700 list-disc">Use <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">--debug</code> flag when troubleshooting API issues</li> </ul> <h3 class="text-xl font-semibold text-gray-900 mt-8 mb-4">Recommended Workflow for Agents</h3></p><p class="my-4 text-gray-700 leading-relaxed"><div class="relative group my-6"> <div class="absolute top-2 right-2 px-2 py-1 text-xs font-medium text-gray-400 bg-gray-800 rounded">text</div> <pre class="bg-gray-900 text-gray-100 p-4 rounded-lg overflow-x-auto text-sm leading-relaxed"><code class="language-text">Step 1: Setup and Authentication Check --------------------------------------- cd <skill_directory> python3 scripts/ms-todo-oauth.py lists # Test auth & see available lists If exit code is 1 and output contains "Not logged in": a. python3 scripts/ms-todo-oauth.py login get b. Present URL to user c. Explain: "Visit this URL, login, and copy the 'code' parameter from callback URL" d. Wait for user to provide authorization code e. python3 scripts/ms-todo-oauth.py login verify "<code>" f. Verify success (exit code 0) Step 2: Task Analysis and List Selection ----------------------------------------- When user requests to add task(s): a. Analyze task context from user's description b. Review available lists (from Step 1 output) c. Choose appropriate list or use default: - Work-related → "Work" - Personal errands → "Personal" or default - Shopping items → "Shopping" - Project-specific → "<ProjectName>" d. If list doesn't exist, it will be auto-created Step 3: Execute Operation -------------------------- Add task with appropriate options: python3 scripts/ms-todo-oauth.py add "Task Title" \ -l "Work" \ -p high \ -d 3 \ -r 2h \ -D "Detailed description" \ -t "tag1,tag2" Step 4: Verify and Report -------------------------- Check exit code: - 0: Success → Confirm to user - 1: Failure → Parse error, provide guidance - 2: Invalid args → Fix command syntax Optionally verify: python3 scripts/ms-todo-oauth.py tasks "<list>" # Show updated list</code></pre> </div></p><p class="my-4 text-gray-700 leading-relaxed"><h3 class="text-xl font-semibold text-gray-900 mt-8 mb-4">Task Title Matching Rules</h3> <ul class="my-4 space-y-2"><li class="ml-6 mb-2 text-gray-700 list-disc"><strong class="font-semibold">Exact match required</strong>: <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">complete</code>, <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">delete</code> commands</li> <li class="ml-6 mb-2 text-gray-700 list-disc"><strong class="font-semibold">Partial/fuzzy match supported</strong>: <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">detail</code>, <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">search</code> commands</li> <li class="ml-6 mb-2 text-gray-700 list-disc"><strong class="font-semibold">Case-insensitive</strong>: All search operations</li> <li class="ml-6 mb-2 text-gray-700 list-disc"><strong class="font-semibold">Best practice</strong>: Use <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">search</code> first to find exact title, then use it in subsequent commands</li> </ul> <strong class="font-semibold">Example workflow:</strong></p><p class="my-4 text-gray-700 leading-relaxed"><div class="relative group my-6"> <div class="absolute top-2 right-2 px-2 py-1 text-xs font-medium text-gray-400 bg-gray-800 rounded">bash</div> <pre class="bg-gray-900 text-gray-100 p-4 rounded-lg overflow-x-auto text-sm leading-relaxed"><code class="language-bash"># Find task with fuzzy search python3 scripts/ms-todo-oauth.py search "report" # Output shows: "Complete Q1 Report" # Use exact title from search results python3 scripts/ms-todo-oauth.py complete "Complete Q1 Report" -l "Work"</code></pre> </div></p><p class="my-4 text-gray-700 leading-relaxed"><h3 class="text-xl font-semibold text-gray-900 mt-8 mb-4">Default List Behavior</h3> <ul class="my-4 space-y-2"><li class="ml-6 mb-2 text-gray-700 list-disc">When <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">-l</code> is not specified, operations use the Microsoft To Do default list</li> <li class="ml-6 mb-2 text-gray-700 list-disc">The default list is typically named "Tasks" (English) or "任务" (Chinese)</li> <li class="ml-6 mb-2 text-gray-700 list-disc">To target a specific list, always provide <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">-l "<ListName>"</code></li> </ul> <h3 class="text-xl font-semibold text-gray-900 mt-8 mb-4">Example Task Categorization</h3></p><p class="my-4 text-gray-700 leading-relaxed"><strong class="font-semibold">User request:</strong> "Add these tasks: buy milk, finish report, call dentist"</p><p class="my-4 text-gray-700 leading-relaxed"><strong class="font-semibold">Agent approach:</strong></p><p class="my-4 text-gray-700 leading-relaxed"><div class="relative group my-6"> <div class="absolute top-2 right-2 px-2 py-1 text-xs font-medium text-gray-400 bg-gray-800 rounded">bash</div> <pre class="bg-gray-900 text-gray-100 p-4 rounded-lg overflow-x-auto text-sm leading-relaxed"><code class="language-bash"># First check available lists python3 scripts/ms-todo-oauth.py lists # Categorize intelligently: python3 scripts/ms-todo-oauth.py add "Buy milk" -l "Shopping" python3 scripts/ms-todo-oauth.py add "Finish report" -l "Work" -p high -d 2 python3 scripts/ms-todo-oauth.py add "Call dentist" -l "Personal" # Or use default list if no specific context: add "Call dentist"</code></pre> </div></p><p class="my-4 text-gray-700 leading-relaxed"><hr class="my-8 border-t border-gray-300"></p><p class="my-4 text-gray-700 leading-relaxed"><h2 class="text-2xl font-bold text-gray-900 mt-10 mb-6 border-b border-gray-200 pb-2">Quick Reference</h2></p><p class="my-4 text-gray-700 leading-relaxed"><h3 class="text-xl font-semibold text-gray-900 mt-8 mb-4">Common Workflows</h3></p><p class="my-4 text-gray-700 leading-relaxed"><strong class="font-semibold">Daily task review:</strong></p><p class="my-4 text-gray-700 leading-relaxed"><div class="relative group my-6"> <div class="absolute top-2 right-2 px-2 py-1 text-xs font-medium text-gray-400 bg-gray-800 rounded">bash</div> <pre class="bg-gray-900 text-gray-100 p-4 rounded-lg overflow-x-auto text-sm leading-relaxed"><code class="language-bash">python3 scripts/ms-todo-oauth.py today # Check today's tasks python3 scripts/ms-todo-oauth.py overdue # Check overdue tasks python3 scripts/ms-todo-oauth.py -v pending -g # Review all pending, grouped</code></pre> </div></p><p class="my-4 text-gray-700 leading-relaxed"><strong class="font-semibold">Adding various task types:</strong></p><p class="my-4 text-gray-700 leading-relaxed"><div class="relative group my-6"> <div class="absolute top-2 right-2 px-2 py-1 text-xs font-medium text-gray-400 bg-gray-800 rounded">bash</div> <pre class="bg-gray-900 text-gray-100 p-4 rounded-lg overflow-x-auto text-sm leading-relaxed"><code class="language-bash"># Simple task (default list) python3 scripts/ms-todo-oauth.py add "Buy milk" # Work task with priority and deadline python3 scripts/ms-todo-oauth.py add "Quarterly review" -l "Work" -p high -d 7 # Task with reminder python3 scripts/ms-todo-oauth.py add "Call client" -r 3h # Detailed task with all options python3 scripts/ms-todo-oauth.py add "Project meeting" \ -l "Work" \ -p high \ -d 2026-03-15 \ -r "2026-03-15 14:30" \ -D "Discuss Q1 goals and resource allocation" \ -t "meeting,important,Q1" # Recurring tasks python3 scripts/ms-todo-oauth.py add "Daily standup" -R daily -l "Work" python3 scripts/ms-todo-oauth.py add "Weekly review" -R weekly -d 7 python3 scripts/ms-todo-oauth.py add "Gym" -R weekdays -l "Personal" python3 scripts/ms-todo-oauth.py add "Monthly report" -R monthly -p high</code></pre> </div></p><p class="my-4 text-gray-700 leading-relaxed"><strong class="font-semibold">Task completion workflow:</strong></p><p class="my-4 text-gray-700 leading-relaxed"><div class="relative group my-6"> <div class="absolute top-2 right-2 px-2 py-1 text-xs font-medium text-gray-400 bg-gray-800 rounded">bash</div> <pre class="bg-gray-900 text-gray-100 p-4 rounded-lg overflow-x-auto text-sm leading-relaxed"><code class="language-bash"># Search for task python3 scripts/ms-todo-oauth.py search "report" # Complete using exact title from search results python3 scripts/ms-todo-oauth.py complete "Quarterly review" -l "Work"</code></pre> </div></p><p class="my-4 text-gray-700 leading-relaxed"><strong class="font-semibold">Data management:</strong></p><p class="my-4 text-gray-700 leading-relaxed"><div class="relative group my-6"> <div class="absolute top-2 right-2 px-2 py-1 text-xs font-medium text-gray-400 bg-gray-800 rounded">bash</div> <pre class="bg-gray-900 text-gray-100 p-4 rounded-lg overflow-x-auto text-sm leading-relaxed"><code class="language-bash"># Export for backup python3 scripts/ms-todo-oauth.py export -o "backup_$(date +%Y%m%d).json" # View statistics python3 scripts/ms-todo-oauth.py stats</code></pre> </div></p><p class="my-4 text-gray-700 leading-relaxed"><hr class="my-8 border-t border-gray-300"></p><p class="my-4 text-gray-700 leading-relaxed"><h2 class="text-2xl font-bold text-gray-900 mt-10 mb-6 border-b border-gray-200 pb-2">Changelog</h2></p><p class="my-4 text-gray-700 leading-relaxed"><h3 class="text-xl font-semibold text-gray-900 mt-8 mb-4">Version 1.1.0 (Current)</h3> <ul class="my-4 space-y-2"><li class="ml-6 mb-2 text-gray-700 list-disc">✅ <strong class="font-semibold">Fixed</strong>: DateTime parsing errors (Microsoft's 7-decimal format)</li> <li class="ml-6 mb-2 text-gray-700 list-disc">✅ <strong class="font-semibold">Fixed</strong>: HTTP method parameter order bugs</li> <li class="ml-6 mb-2 text-gray-700 list-disc">✅ <strong class="font-semibold">Fixed</strong>: Missing <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">start_date</code> parameter in <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">create_task()</code></li> <li class="ml-6 mb-2 text-gray-700 list-disc">✅ <strong class="font-semibold">Fixed</strong>: Missing <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">complete_task()</code> method</li> <li class="ml-6 mb-2 text-gray-700 list-disc">✅ <strong class="font-semibold">Fixed</strong>: Error exit codes now correctly return 1 on failure</li> <li class="ml-6 mb-2 text-gray-700 list-disc">✅ <strong class="font-semibold">Added</strong>: Comprehensive test suite (29 automated tests)</li> <li class="ml-6 mb-2 text-gray-700 list-disc">✅ <strong class="font-semibold">Added</strong>: Better error messages and troubleshooting</li> <li class="ml-6 mb-2 text-gray-700 list-disc">✅ <strong class="font-semibold">Improved</strong>: OAuth2 authentication flow documentation</li> <li class="ml-6 mb-2 text-gray-700 list-disc">✅ <strong class="font-semibold">Improved</strong>: Unicode and emoji support documentation</li> <li class="ml-6 mb-2 text-gray-700 list-disc">✅ <strong class="font-semibold">Improved</strong>: Agent usage guidelines</li> </ul> <h3 class="text-xl font-semibold text-gray-900 mt-8 mb-4">Version 1.0.2 (Previous)</h3> <ul class="my-4 space-y-2"><li class="ml-6 mb-2 text-gray-700 list-disc">Initial release with OAuth2 authentication</li> <li class="ml-6 mb-2 text-gray-700 list-disc">Basic task and list management</li> <li class="ml-6 mb-2 text-gray-700 list-disc">Recurring task support</li> <li class="ml-6 mb-2 text-gray-700 list-disc">Multiple task views</li> <li class="ml-6 mb-2 text-gray-700 list-disc">Data export functionality</li> </ul> <hr class="my-8 border-t border-gray-300"></p><p class="my-4 text-gray-700 leading-relaxed"><h2 class="text-2xl font-bold text-gray-900 mt-10 mb-6 border-b border-gray-200 pb-2">Troubleshooting</h2></p><p class="my-4 text-gray-700 leading-relaxed"><h3 class="text-xl font-semibold text-gray-900 mt-8 mb-4">Authentication Issues</h3></p><p class="my-4 text-gray-700 leading-relaxed"><strong class="font-semibold">Problem:</strong> <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">❌ Not logged in</code> <ul class="my-4 space-y-2"><li class="ml-6 mb-2 text-gray-700 list-disc"><strong class="font-semibold">Solution</strong>: Run <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">login get</code>, complete browser flow, then <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">login verify <code></code></li> </ul> <strong class="font-semibold">Problem:</strong> <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">❌ Token acquisition failed: invalid_grant</code> <ul class="my-4 space-y-2"><li class="ml-6 mb-2 text-gray-700 list-disc"><strong class="font-semibold">Cause</strong>: Authorization code already used or expired</li> <li class="ml-6 mb-2 text-gray-700 list-disc"><strong class="font-semibold">Solution</strong>: Run <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">login get</code> again to get a fresh code</li> </ul> <strong class="font-semibold">Problem:</strong> Login worked but now getting "Not logged in" again <ul class="my-4 space-y-2"><li class="ml-6 mb-2 text-gray-700 list-disc"><strong class="font-semibold">Cause</strong>: Token expired and auto-refresh failed</li> <li class="ml-6 mb-2 text-gray-700 list-disc"><strong class="font-semibold">Solution</strong>: Run <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">--reauth</code> to force fresh login:</li> </ul> <div class="relative group my-6"> <div class="absolute top-2 right-2 px-2 py-1 text-xs font-medium text-gray-400 bg-gray-800 rounded">bash</div> <pre class="bg-gray-900 text-gray-100 p-4 rounded-lg overflow-x-auto text-sm leading-relaxed"><code class="language-bash">python3 scripts/ms-todo-oauth.py --reauth lists</code></pre> </div></p><p class="my-4 text-gray-700 leading-relaxed"><h3 class="text-xl font-semibold text-gray-900 mt-8 mb-4">Import/Dependency Issues</h3></p><p class="my-4 text-gray-700 leading-relaxed"><strong class="font-semibold">Problem:</strong> <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">ModuleNotFoundError: No module named 'msal'</code> <ul class="my-4 space-y-2"><li class="ml-6 mb-2 text-gray-700 list-disc"><strong class="font-semibold">Solution</strong>: Install dependencies: <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">pip install -r requirements.txt</code></li> </ul> <h3 class="text-xl font-semibold text-gray-900 mt-8 mb-4">API/Network Issues</h3></p><p class="my-4 text-gray-700 leading-relaxed"><strong class="font-semibold">Problem:</strong> Connection timeout or network errors <ul class="my-4 space-y-2"><li class="ml-6 mb-2 text-gray-700 list-disc"><strong class="font-semibold">Check</strong>: Internet connection</li> <li class="ml-6 mb-2 text-gray-700 list-disc"><strong class="font-semibold">Check</strong>: Can you access https://graph.microsoft.com in browser?</li> <li class="ml-6 mb-2 text-gray-700 list-disc"><strong class="font-semibold">Try</strong>: Using <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">--debug</code> flag to see full API request/response</li> </ul> <strong class="font-semibold">Problem:</strong> Unexpected API errors <ul class="my-4 space-y-2"><li class="ml-6 mb-2 text-gray-700 list-disc"><strong class="font-semibold">Try</strong>: Re-authenticate: <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">python3 scripts/ms-todo-oauth.py --reauth lists</code></li> <li class="ml-6 mb-2 text-gray-700 list-disc"><strong class="font-semibold">Try</strong>: Debug mode: <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">python3 scripts/ms-todo-oauth.py --debug <command></code></li> </ul> <h3 class="text-xl font-semibold text-gray-900 mt-8 mb-4">Task/List Not Found</h3></p><p class="my-4 text-gray-700 leading-relaxed"><strong class="font-semibold">Problem:</strong> <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">❌ Task not found: <title></code> <ul class="my-4 space-y-2"><li class="ml-6 mb-2 text-gray-700 list-disc"><strong class="font-semibold">Solution</strong>: Use <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">search</code> to find exact title</li> <li class="ml-6 mb-2 text-gray-700 list-disc"><strong class="font-semibold">Note</strong>: <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">complete</code> and <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">delete</code> require exact title match</li> </ul> <strong class="font-semibold">Problem:</strong> <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">❌ List not found: <name></code> <ul class="my-4 space-y-2"><li class="ml-6 mb-2 text-gray-700 list-disc"><strong class="font-semibold">Solution</strong>: Run <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">lists</code> to see exact list names</li> <li class="ml-6 mb-2 text-gray-700 list-disc"><strong class="font-semibold">Note</strong>: List names are case-sensitive</li> </ul> <h3 class="text-xl font-semibold text-gray-900 mt-8 mb-4">Test Failures</h3></p><p class="my-4 text-gray-700 leading-relaxed"><strong class="font-semibold">Problem:</strong> Tests failing with datetime errors <ul class="my-4 space-y-2"><li class="ml-6 mb-2 text-gray-700 list-disc"><strong class="font-semibold">Solution</strong>: Ensure you've applied all v1.1.0 fixes</li> <li class="ml-6 mb-2 text-gray-700 list-disc"><strong class="font-semibold">Check</strong>: Verify <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">_parse_ms_datetime()</code> helper function exists</li> </ul> <strong class="font-semibold">Problem:</strong> Tests failing with "Not logged in" <ul class="my-4 space-y-2"><li class="ml-6 mb-2 text-gray-700 list-disc"><strong class="font-semibold">Solution</strong>: Authenticate before running tests:</li> </ul> <div class="relative group my-6"> <div class="absolute top-2 right-2 px-2 py-1 text-xs font-medium text-gray-400 bg-gray-800 rounded">bash</div> <pre class="bg-gray-900 text-gray-100 p-4 rounded-lg overflow-x-auto text-sm leading-relaxed"><code class="language-bash">python3 scripts/ms-todo-oauth.py login get # Complete browser flow python3 scripts/ms-todo-oauth.py login verify <code> # Then run tests python3 test_ms_todo_oauth.py</code></pre> </div></p><p class="my-4 text-gray-700 leading-relaxed"><hr class="my-8 border-t border-gray-300"></p><p class="my-4 text-gray-700 leading-relaxed"><h2 class="text-2xl font-bold text-gray-900 mt-10 mb-6 border-b border-gray-200 pb-2">Additional Resources</h2> <ul class="my-4 space-y-2"><li class="ml-6 mb-2 text-gray-700 list-disc"><strong class="font-semibold">Test Suite</strong>: <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">test_ms_todo_oauth.py</code> - Automated tests</li> <li class="ml-6 mb-2 text-gray-700 list-disc"><strong class="font-semibold">Manual Tests</strong>: <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">MANUAL_TEST_CHECKLIST.txt</code> - Step-by-step testing guide</li> <li class="ml-6 mb-2 text-gray-700 list-disc"><strong class="font-semibold">Quick Reference</strong>: <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">QUICK_REFERENCE.txt</code> - Command cheat sheet</li> <li class="ml-6 mb-2 text-gray-700 list-disc"><strong class="font-semibold">Bug Fixes</strong>: <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">COMPLETE_FIX_PATCH.txt</code> - Documentation of v1.1.0 fixes</li> </ul> <hr class="my-8 border-t border-gray-300"></p><p class="my-4 text-gray-700 leading-relaxed"><h2 class="text-2xl font-bold text-gray-900 mt-10 mb-6 border-b border-gray-200 pb-2">Support & Contributing</h2></p><p class="my-4 text-gray-700 leading-relaxed"><strong class="font-semibold">Reporting Issues:</strong> <ul class="my-4 space-y-2"><li class="ml-6 mb-2 text-gray-700 list-disc">Provide error message and command used</li> <li class="ml-6 mb-2 text-gray-700 list-disc">Include output from <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">--debug</code> flag if applicable</li> <li class="ml-6 mb-2 text-gray-700 list-disc">Note your Python version: <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">python3 --version</code></li> <li class="ml-6 mb-2 text-gray-700 list-disc">Note your OS: Windows/Mac/Linux</li> </ul> <strong class="font-semibold">Testing New Features:</strong> <ul class="my-4 space-y-2"><li class="ml-6 mb-2 text-gray-700 list-disc">Always run the test suite after code changes</li> <li class="ml-6 mb-2 text-gray-700 list-disc">Add new test cases to <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">test_ms_todo_oauth.py</code> for new features</li> <li class="ml-6 mb-2 text-gray-700 list-disc">Update <code class="px-1.5 py-0.5 text-sm text-primary-700 bg-primary-50 rounded font-mono border border-primary-200">MANUAL_TEST_CHECKLIST.txt</code> with manual test procedures</li> </ul> <hr class="my-8 border-t border-gray-300"></p><p class="my-4 text-gray-700 leading-relaxed"><h2 class="text-2xl font-bold text-gray-900 mt-10 mb-6 border-b border-gray-200 pb-2">License</h2></p><p class="my-4 text-gray-700 leading-relaxed">MIT License - See LICENSE file for details</p><p class="my-4 text-gray-700 leading-relaxed"><hr class="my-8 border-t border-gray-300"></p><p class="my-4 text-gray-700 leading-relaxed"><strong class="font-semibold">Version</strong>: 1.1.0 <strong class="font-semibold">Last Updated</strong>: 2026-02-13 <strong class="font-semibold">Status</strong>: ✅ Fully Tested & Production Ready </p></div> </div> </div> <!-- Installation --> <section class="card" aria-labelledby="installation-heading" data-astro-cid-jrlgpo3w> <h2 id="installation-heading" class="text-2xl font-bold text-gray-900 mb-4" data-astro-cid-jrlgpo3w>Installation</h2> <div class="code-block-container relative group " data-astro-cid-i4kugh4e> <div class="flex items-center justify-between px-4 py-2 bg-gray-800 border-b border-gray-700 rounded-t-lg" data-astro-cid-i4kugh4e> <span class="text-sm text-gray-300 font-mono" data-astro-cid-i4kugh4e>Terminal</span> <span class="text-xs text-gray-500 uppercase" data-astro-cid-i4kugh4e>bash</span> </div> <div class="relative" data-astro-cid-i4kugh4e> <pre class="!mt-0 !rounded-t-none" data-astro-cid-i4kugh4e><code id="code-o6ntnv4z4" class="language-bash" data-astro-cid-i4kugh4e> openclaw install ms-todo-oauth </code></pre> <!-- Copy Button --> <button class="copy-button absolute top-2 right-2 p-2 bg-gray-700 hover:bg-gray-600 text-gray-300 rounded-lg transition-all duration-200 opacity-0 group-hover:opacity-100 focus:opacity-100" data-code-id="code-o6ntnv4z4" aria-label="Copy code to clipboard" data-astro-cid-i4kugh4e> <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" data-astro-cid-i4kugh4e> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z" data-astro-cid-i4kugh4e></path> </svg> <span class="copy-text sr-only" data-astro-cid-i4kugh4e>Copy</span> </button> <!-- Copied Indicator --> <div class="copied-indicator absolute top-2 right-14 px-3 py-1.5 bg-green-600 text-white text-sm rounded-lg opacity-0 transition-opacity duration-200 pointer-events-none" data-astro-cid-i4kugh4e> Copied! </div> </div> </div> <script>(function(){const codeId = "code-o6ntnv4z4"; const copyButton = document.querySelector(`[data-code-id="${codeId}"]`); const copiedIndicator = document.querySelector('.copied-indicator'); if (copyButton) { copyButton.addEventListener('click', async () => { const codeElement = document.getElementById(codeId); const code = codeElement?.textContent || ''; try { await navigator.clipboard.writeText(code); // Show copied state copyButton.classList.add('copied'); copiedIndicator?.classList.remove('opacity-0'); // Reset after 2 seconds setTimeout(() => { copyButton.classList.remove('copied'); copiedIndicator?.classList.add('opacity-0'); }, 2000); } catch (err) { console.error('Failed to copy code:', err); } }); } })();</script> </section> <!-- Verification Command (if available from enhanced data) --> <!-- Code Examples (if available) --> <div class="card" data-astro-cid-cpq6uwpo><h2 class="text-2xl font-bold text-gray-900 mb-6 flex items-center" data-astro-cid-cpq6uwpo><span class="text-2xl mr-2" data-astro-cid-cpq6uwpo>💻</span>Code Examples</h2><div class="space-y-6" data-astro-cid-cpq6uwpo><div class="code-example" data-astro-cid-cpq6uwpo><h3 class="text-lg font-semibold text-gray-900 mb-2" data-astro-cid-cpq6uwpo># pip install -r requirements.txt</h3><div class="relative" data-astro-cid-cpq6uwpo><div class="flex items-center justify-between bg-gray-800 text-gray-300 px-4 py-2 rounded-t-lg text-sm" data-astro-cid-cpq6uwpo><span class="font-mono" data-astro-cid-cpq6uwpo>-pip-install--r-requirementstxt.txt</span><button class="copy-btn px-3 py-1 bg-primary-600 hover:bg-primary-700 text-white rounded text-xs font-medium transition-colors" data-astro-cid-cpq6uwpo> Copy Code </button></div><pre class="bg-gray-900 text-gray-100 p-4 rounded-b-lg overflow-x-auto text-sm leading-relaxed" data-astro-cid-cpq6uwpo><code class="language-text" data-astro-cid-cpq6uwpo>**Dependencies:** - `msal` (Microsoft Authentication Library) - Official Microsoft OAuth library - `requests` - HTTP client for API calls - Specified in `requirements.txt` ### Environment Verification After installation, verify the setup:</code></pre></div></div><div class="code-example" data-astro-cid-cpq6uwpo><h3 class="text-lg font-semibold text-gray-900 mb-2" data-astro-cid-cpq6uwpo># Expected: Command help text should be displayed</h3><div class="relative" data-astro-cid-cpq6uwpo><div class="flex items-center justify-between bg-gray-800 text-gray-300 px-4 py-2 rounded-t-lg text-sm" data-astro-cid-cpq6uwpo><span class="font-mono" data-astro-cid-cpq6uwpo>-expected-command-help-text-should-be-displayed.txt</span><button class="copy-btn px-3 py-1 bg-primary-600 hover:bg-primary-700 text-white rounded text-xs font-medium transition-colors" data-astro-cid-cpq6uwpo> Copy Code </button></div><pre class="bg-gray-900 text-gray-100 p-4 rounded-b-lg overflow-x-auto text-sm leading-relaxed" data-astro-cid-cpq6uwpo><code class="language-text" data-astro-cid-cpq6uwpo>**Troubleshooting:** - If `Python not found`, install Python 3.9 or higher from https://python.org ### Testing (Optional but Recommended) Verify all functionality works correctly:</code></pre></div></div><div class="code-example" data-astro-cid-cpq6uwpo><h3 class="text-lg font-semibold text-gray-900 mb-2" data-astro-cid-cpq6uwpo># Expected: All tests pass (100% pass rate)</h3><div class="relative" data-astro-cid-cpq6uwpo><div class="flex items-center justify-between bg-gray-800 text-gray-300 px-4 py-2 rounded-t-lg text-sm" data-astro-cid-cpq6uwpo><span class="font-mono" data-astro-cid-cpq6uwpo>-expected-all-tests-pass-100-pass-rate.txt</span><button class="copy-btn px-3 py-1 bg-primary-600 hover:bg-primary-700 text-white rounded text-xs font-medium transition-colors" data-astro-cid-cpq6uwpo> Copy Code </button></div><pre class="bg-gray-900 text-gray-100 p-4 rounded-b-lg overflow-x-auto text-sm leading-relaxed" data-astro-cid-cpq6uwpo><code class="language-text" data-astro-cid-cpq6uwpo>See [Testing](#testing) section for details. ### Security Notes - Uses official Microsoft Graph API via Microsoft's `msal` library - All code is plain Python (.py files), readable and auditable - Tokens stored locally in `~/.mstodo_token_cache.json` - All API calls go directly to Microsoft endpoints (graph.microsoft.com) - OAuth2 standard authentication flow - No third-party services involved ## Command Reference All commands follow this pattern:</code></pre></div></div><div class="code-example" data-astro-cid-cpq6uwpo><h3 class="text-lg font-semibold text-gray-900 mb-2" data-astro-cid-cpq6uwpo>python3 scripts/ms-todo-oauth.py [GLOBAL_OPTIONS] <command> [COMMAND_OPTIONS]</h3><div class="relative" data-astro-cid-cpq6uwpo><div class="flex items-center justify-between bg-gray-800 text-gray-300 px-4 py-2 rounded-t-lg text-sm" data-astro-cid-cpq6uwpo><span class="font-mono" data-astro-cid-cpq6uwpo>python3-scriptsms-todo-oauthpy-globaloptions-command-commandoptions.txt</span><button class="copy-btn px-3 py-1 bg-primary-600 hover:bg-primary-700 text-white rounded text-xs font-medium transition-colors" data-astro-cid-cpq6uwpo> Copy Code </button></div><pre class="bg-gray-900 text-gray-100 p-4 rounded-b-lg overflow-x-auto text-sm leading-relaxed" data-astro-cid-cpq6uwpo><code class="language-text" data-astro-cid-cpq6uwpo>### Global 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.** | | `--reauth` | Force re-authentication by clearing the token cache and starting fresh login | > ⚠️ **Common mistake**: Global options MUST come before the subcommand. > > - ✅ `python3 scripts/ms-todo-oauth.py -v lists` > - ✅ `python3 scripts/ms-todo-oauth.py --debug add "Task"` > - ❌ `python3 scripts/ms-todo-oauth.py lists -v` --- ### Authentication Authentication uses OAuth2 authorization code flow, designed for both interactive and automated environments. #### `login get` — Get OAuth2 authorization URL</code></pre></div></div><div class="code-example" data-astro-cid-cpq6uwpo><h3 class="text-lg font-semibold text-gray-900 mb-2" data-astro-cid-cpq6uwpo>======================================================================</h3><div class="relative" data-astro-cid-cpq6uwpo><div class="flex items-center justify-between bg-gray-800 text-gray-300 px-4 py-2 rounded-t-lg text-sm" data-astro-cid-cpq6uwpo><span class="font-mono" data-astro-cid-cpq6uwpo>.txt</span><button class="copy-btn px-3 py-1 bg-primary-600 hover:bg-primary-700 text-white rounded text-xs font-medium transition-colors" data-astro-cid-cpq6uwpo> Copy Code </button></div><pre class="bg-gray-900 text-gray-100 p-4 rounded-b-lg overflow-x-auto text-sm leading-relaxed" data-astro-cid-cpq6uwpo><code class="language-text" data-astro-cid-cpq6uwpo>**What to do:** 1. Open the provided URL in your browser 2. Sign in with your Microsoft account 3. Grant permissions when prompted 4. You'll be redirected to a URL like: `http://localhost:8000/callback?code=M.R3_BAY.abc123...` 5. Copy the entire code after `code=` (usually a long string starting with `M.R3_BAY.`) **Agent behavior**: Present the URL to the user and explain they need to: 1. Visit the URL 2. Complete the login 3. Copy the authorization code from the callback URL 4. Provide it to you #### `login verify` — Complete login with authorization code</code></pre></div></div><div class="code-example" data-astro-cid-cpq6uwpo><h3 class="text-lg font-semibold text-gray-900 mb-2" data-astro-cid-cpq6uwpo>Description: AADSTS54005: OAuth2 Authorization code was already redeemed...</h3><div class="relative" data-astro-cid-cpq6uwpo><div class="flex items-center justify-between bg-gray-800 text-gray-300 px-4 py-2 rounded-t-lg text-sm" data-astro-cid-cpq6uwpo><span class="font-mono" data-astro-cid-cpq6uwpo>description-aadsts54005-oauth2-authorization-code-was-already-redeemed.txt</span><button class="copy-btn px-3 py-1 bg-primary-600 hover:bg-primary-700 text-white rounded text-xs font-medium transition-colors" data-astro-cid-cpq6uwpo> Copy Code </button></div><pre class="bg-gray-900 text-gray-100 p-4 rounded-b-lg overflow-x-auto text-sm leading-relaxed" data-astro-cid-cpq6uwpo><code class="language-text" data-astro-cid-cpq6uwpo>**Exit code**: 0 on success, 1 on failure. **Important notes:** - Each authorization code can only be used ONCE - If verification fails, you need to run `login get` again to get a new code - Once successfully logged in, the token is cached and you won't need to login again unless: - You run `logout` - You run `--reauth` - The token expires and cannot be auto-refreshed #### `logout` — Clear saved login</code></pre></div></div><div class="code-example" data-astro-cid-cpq6uwpo><h3 class="text-lg font-semibold text-gray-900 mb-2" data-astro-cid-cpq6uwpo>python3 scripts/ms-todo-oauth.py logout</h3><div class="relative" data-astro-cid-cpq6uwpo><div class="flex items-center justify-between bg-gray-800 text-gray-300 px-4 py-2 rounded-t-lg text-sm" data-astro-cid-cpq6uwpo><span class="font-mono" data-astro-cid-cpq6uwpo>python3-scriptsms-todo-oauthpy-logout.txt</span><button class="copy-btn px-3 py-1 bg-primary-600 hover:bg-primary-700 text-white rounded text-xs font-medium transition-colors" data-astro-cid-cpq6uwpo> Copy Code </button></div><pre class="bg-gray-900 text-gray-100 p-4 rounded-b-lg overflow-x-auto text-sm leading-relaxed" data-astro-cid-cpq6uwpo><code class="language-text" data-astro-cid-cpq6uwpo>Output: `✓ Login information cleared` 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. --- ### List Management #### `lists` — List all task lists</code></pre></div></div><div class="code-example" data-astro-cid-cpq6uwpo><h3 class="text-lg font-semibold text-gray-900 mb-2" data-astro-cid-cpq6uwpo>python3 scripts/ms-todo-oauth.py create-list "<name>"</h3><div class="relative" data-astro-cid-cpq6uwpo><div class="flex items-center justify-between bg-gray-800 text-gray-300 px-4 py-2 rounded-t-lg text-sm" data-astro-cid-cpq6uwpo><span class="font-mono" data-astro-cid-cpq6uwpo>python3-scriptsms-todo-oauthpy-create-list-name.txt</span><button class="copy-btn px-3 py-1 bg-primary-600 hover:bg-primary-700 text-white rounded text-xs font-medium transition-colors" data-astro-cid-cpq6uwpo> Copy Code </button></div><pre class="bg-gray-900 text-gray-100 p-4 rounded-b-lg overflow-x-auto text-sm leading-relaxed" data-astro-cid-cpq6uwpo><code class="language-text" data-astro-cid-cpq6uwpo>| Argument | Required | Description | | -------- | -------- | ----------------------------------------------- | | `name` | Yes | Name of the new list (supports Unicode/Chinese) | **Example:**</code></pre></div></div><div class="code-example" data-astro-cid-cpq6uwpo><h3 class="text-lg font-semibold text-gray-900 mb-2" data-astro-cid-cpq6uwpo>python3 scripts/ms-todo-oauth.py create-list "项目 A"</h3><div class="relative" data-astro-cid-cpq6uwpo><div class="flex items-center justify-between bg-gray-800 text-gray-300 px-4 py-2 rounded-t-lg text-sm" data-astro-cid-cpq6uwpo><span class="font-mono" data-astro-cid-cpq6uwpo>python3-scriptsms-todo-oauthpy-create-list--a.txt</span><button class="copy-btn px-3 py-1 bg-primary-600 hover:bg-primary-700 text-white rounded text-xs font-medium transition-colors" data-astro-cid-cpq6uwpo> Copy Code </button></div><pre class="bg-gray-900 text-gray-100 p-4 rounded-b-lg overflow-x-auto text-sm leading-relaxed" data-astro-cid-cpq6uwpo><code class="language-text" data-astro-cid-cpq6uwpo>Output: `✓ List created: 项目 A` #### `delete-list` — Delete a list</code></pre></div></div><div class="code-example" data-astro-cid-cpq6uwpo><h3 class="text-lg font-semibold text-gray-900 mb-2" data-astro-cid-cpq6uwpo>python3 scripts/ms-todo-oauth.py delete-list "<name>" [-y]</h3><div class="relative" data-astro-cid-cpq6uwpo><div class="flex items-center justify-between bg-gray-800 text-gray-300 px-4 py-2 rounded-t-lg text-sm" data-astro-cid-cpq6uwpo><span class="font-mono" data-astro-cid-cpq6uwpo>python3-scriptsms-todo-oauthpy-delete-list-name--y.txt</span><button class="copy-btn px-3 py-1 bg-primary-600 hover:bg-primary-700 text-white rounded text-xs font-medium transition-colors" data-astro-cid-cpq6uwpo> Copy Code </button></div><pre class="bg-gray-900 text-gray-100 p-4 rounded-b-lg overflow-x-auto text-sm leading-relaxed" data-astro-cid-cpq6uwpo><code class="language-text" data-astro-cid-cpq6uwpo>| 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. All tasks in the list will be deleted. Consider asking the user before deleting important lists. Output: `✓ List deleted: <name>` **Exit code**: 1 if list not found, 0 on success --- ### Task Operations #### `add` — Add a new task</code></pre></div></div></div></div> <!-- Configuration Table (if available) --> <!-- Requirements --> <!-- Code Example --> <!-- Testing Notes --> <!-- Tags --> <div class="card" data-astro-cid-jrlgpo3w> <h2 class="text-2xl font-bold text-gray-900 mb-4" data-astro-cid-jrlgpo3w>Tags</h2> <div class="flex flex-wrap gap-2" data-astro-cid-jrlgpo3w> <span class="px-3 py-1.5 text-sm text-gray-600 bg-gray-50 rounded-lg border border-gray-200" data-astro-cid-jrlgpo3w> #git_and-github </span><span class="px-3 py-1.5 text-sm text-gray-600 bg-gray-50 rounded-lg border border-gray-200" data-astro-cid-jrlgpo3w> #api </span><span class="px-3 py-1.5 text-sm text-gray-600 bg-gray-50 rounded-lg border border-gray-200" data-astro-cid-jrlgpo3w> #cli </span> </div> </div> </div> <!-- Sidebar --> <div class="space-y-6" data-astro-cid-jrlgpo3w> <!-- Quick Info --> <div class="card" data-astro-cid-jrlgpo3w> <h3 class="font-semibold text-gray-900 mb-4" data-astro-cid-jrlgpo3w>Quick Info</h3> <div class="space-y-3 text-sm" data-astro-cid-jrlgpo3w> <div class="flex justify-between" data-astro-cid-jrlgpo3w> <span class="text-gray-600" data-astro-cid-jrlgpo3w>Category</span> <span class="font-medium text-gray-900" data-astro-cid-jrlgpo3w>Development</span> </div> <div class="flex justify-between" data-astro-cid-jrlgpo3w> <span class="text-gray-600" data-astro-cid-jrlgpo3w>Model</span> <span class="font-medium text-gray-900" data-astro-cid-jrlgpo3w>Claude 3.5</span> </div> <div class="flex justify-between" data-astro-cid-jrlgpo3w> <span class="text-gray-600" data-astro-cid-jrlgpo3w>Complexity</span> <span class="font-medium text-gray-900" data-astro-cid-jrlgpo3w>One-Click</span> </div> <div class="flex justify-between" data-astro-cid-jrlgpo3w> <span class="text-gray-600" data-astro-cid-jrlgpo3w>Author</span> <span class="font-medium text-gray-900" data-astro-cid-jrlgpo3w>nathanatgit</span> </div> <div class="flex justify-between" data-astro-cid-jrlgpo3w> <span class="text-gray-600" data-astro-cid-jrlgpo3w>Last Updated</span> <span class="font-medium text-gray-900" data-astro-cid-jrlgpo3w>3/10/2026</span> </div> </div> </div> <!-- Model Badge --> <div class="card bg-gradient-to-br from-blue-50 to-indigo-50 border-blue-100" data-astro-cid-jrlgpo3w> <div class="flex items-center justify-between" data-astro-cid-jrlgpo3w> <div class="flex items-center space-x-3" data-astro-cid-jrlgpo3w> <div class="text-3xl" data-astro-cid-jrlgpo3w>🚀</div> <div data-astro-cid-jrlgpo3w> <div class="text-sm text-gray-600" data-astro-cid-jrlgpo3w>Optimized for</div> <div class="font-semibold text-gray-900" data-astro-cid-jrlgpo3w>Claude 3.5</div> </div> </div> <span class="inline-flex items-center gap-1.5 px-2.5 py-1 text-xs font-medium rounded-lg bg-purple-50 text-purple-700 border border-purple-200 hover:bg-purple-100 transition-colors" title="Optimized for Claude 3.5 Sonnet" data-astro-cid-3xlfahoe> <span data-astro-cid-3xlfahoe>🧠</span> </span> </div> </div> <!-- Install CTA --> <div class="card bg-gradient-to-br from-primary-500 to-primary-600 text-white border-0" data-astro-cid-jrlgpo3w> <h3 class="font-semibold text-lg mb-2" data-astro-cid-jrlgpo3w>Ready to Install?</h3> <p class="text-primary-100 text-sm mb-4" data-astro-cid-jrlgpo3w> Get started with this skill in seconds </p> <div class="bg-white/20 backdrop-blur-sm rounded-lg p-3 font-mono text-sm" data-astro-cid-jrlgpo3w> openclaw install ms-todo-oauth </div> </div> <!-- External Links (if available) --> <div class="card" data-astro-cid-jrlgpo3w> <h3 class="font-semibold text-gray-900 mb-4" data-astro-cid-jrlgpo3w>Resources</h3> <div class="space-y-3" data-astro-cid-jrlgpo3w> <a href="https://github.com/openclaw/skills/tree/main/skills/nathanatgit/ms-todo-oauth/SKILL.md" target="_blank" rel="noopener noreferrer" class="flex items-center justify-between p-3 rounded-lg border border-gray-200 hover:border-primary-300 hover:bg-primary-50 transition-colors" data-astro-cid-jrlgpo3w> <div class="flex items-center space-x-3" data-astro-cid-jrlgpo3w> <div class="text-2xl" data-astro-cid-jrlgpo3w>📂</div> <div data-astro-cid-jrlgpo3w> <div class="font-medium text-gray-900" data-astro-cid-jrlgpo3w>OpenClaw Skills</div> <div class="text-xs text-gray-500" data-astro-cid-jrlgpo3w>View on OpenClaw GitHub</div> </div> </div> <span class="text-primary-600" data-astro-cid-jrlgpo3w>→</span> </a> </div> </div> </div> </div> </div> </section> <section class="section bg-gray-50" data-astro-cid-jrlgpo3w> <div class="container" data-astro-cid-jrlgpo3w> <h2 class="text-2xl font-bold text-gray-900 mb-6" data-astro-cid-jrlgpo3w>Related Skills</h2> <div class="grid md:grid-cols-2 lg:grid-cols-3 gap-6" data-astro-cid-jrlgpo3w> <a href="/skills/4claw/" class="skill-card group block" data-astro-cid-rwasicqo> <!-- Header --> <div class="flex items-start justify-between mb-4" data-astro-cid-rwasicqo> <div class="flex-1" data-astro-cid-rwasicqo> <div class="flex items-center space-x-2 mb-2" data-astro-cid-rwasicqo> <span class="inline-flex items-center px-2 py-0.5 text-xs font-semibold text-green-700 bg-green-50 rounded-full border border-green-200" data-astro-cid-rwasicqo> ✓ Verified </span> <span class="inline-flex items-center px-2 py-0.5 text-xs font-medium text-gray-600 bg-gray-100 rounded-full" data-astro-cid-rwasicqo> 💻 Development </span> </div> <h3 class="text-lg font-semibold text-gray-900 group-hover:text-primary-600 transition-colors" data-astro-cid-rwasicqo> 4claw </h3> </div> </div> <!-- Description --> <p class="text-sm text-gray-600 mb-4 line-clamp-2" data-astro-cid-rwasicqo> 4claw — a moderated imageboard for AI agents. </p> <!-- Badges --> <div class="flex flex-wrap gap-2 mb-4" data-astro-cid-rwasicqo> <span class="inline-flex items-center gap-1.5 px-2.5 py-1 text-xs font-medium rounded-lg bg-purple-50 text-purple-700 border border-purple-200 hover:bg-purple-100 transition-colors" title="Optimized for Claude 3.5 Sonnet" data-astro-cid-3xlfahoe> <span data-astro-cid-3xlfahoe>🧠</span> <span data-astro-cid-3xlfahoe>Claude-Ready</span> </span> <span class="inline-flex items-center px-2.5 py-1 text-xs font-medium rounded-lg class={complexityInfo.level === 1 ? 'text-green-700 bg-green-50' : complexityInfo.level === 2 ? 'text-blue-700 bg-blue-50' : 'text-purple-700 bg-purple-50'}> {complexityInfo.level === 1 ? '⚡' : complexityInfo.level === 2 ? '🔗' : '🧠'} {complexityInfo.name} </span> </div> <!-- Tags --> {skill.tags.length > 0 && ( <div class=" flex flex-wrap gap-1.5 mb-4" data-astro-cid-rwasicqo> <span class="inline-block px-2 py-1 text-xs text-gray-500 bg-gray-50 rounded border border-gray-100" data-astro-cid-rwasicqo> #ai_and-llms </span> </span></div> )} <!-- Footer Stats --> <div class="flex items-center justify-between pt-4 border-t border-gray-100" data-astro-cid-rwasicqo> <div class="flex items-center space-x-4 text-sm text-gray-500" data-astro-cid-rwasicqo> <div class="flex items-center space-x-1" data-astro-cid-rwasicqo> <span class="text-yellow-500" data-astro-cid-rwasicqo>★</span> <span class="font-medium" data-astro-cid-rwasicqo>4.4</span> <span class="text-xs" data-astro-cid-rwasicqo>(118)</span> </div> <div class="flex items-center space-x-1" data-astro-cid-rwasicqo> <span data-astro-cid-rwasicqo>↓</span> <span class="font-medium" data-astro-cid-rwasicqo>4,990</span> </div> </div> <div class="text-xs text-gray-400" data-astro-cid-rwasicqo> v1.0.0 </div> </div> </a> <a href="/skills/aap-passport/" class="skill-card group block" data-astro-cid-rwasicqo> <!-- Header --> <div class="flex items-start justify-between mb-4" data-astro-cid-rwasicqo> <div class="flex-1" data-astro-cid-rwasicqo> <div class="flex items-center space-x-2 mb-2" data-astro-cid-rwasicqo> <span class="inline-flex items-center px-2 py-0.5 text-xs font-semibold text-green-700 bg-green-50 rounded-full border border-green-200" data-astro-cid-rwasicqo> ✓ Verified </span> <span class="inline-flex items-center px-2 py-0.5 text-xs font-medium text-gray-600 bg-gray-100 rounded-full" data-astro-cid-rwasicqo> 💻 Development </span> </div> <h3 class="text-lg font-semibold text-gray-900 group-hover:text-primary-600 transition-colors" data-astro-cid-rwasicqo> Aap Passport </h3> </div> </div> <!-- Description --> <p class="text-sm text-gray-600 mb-4 line-clamp-2" data-astro-cid-rwasicqo> Agent Attestation Protocol - The Reverse Turing Test. </p> <!-- Badges --> <div class="flex flex-wrap gap-2 mb-4" data-astro-cid-rwasicqo> <span class="inline-flex items-center gap-1.5 px-2.5 py-1 text-xs font-medium rounded-lg bg-purple-50 text-purple-700 border border-purple-200 hover:bg-purple-100 transition-colors" title="Optimized for Claude 3.5 Sonnet" data-astro-cid-3xlfahoe> <span data-astro-cid-3xlfahoe>🧠</span> <span data-astro-cid-3xlfahoe>Claude-Ready</span> </span> <span class="inline-flex items-center px-2.5 py-1 text-xs font-medium rounded-lg class={complexityInfo.level === 1 ? 'text-green-700 bg-green-50' : complexityInfo.level === 2 ? 'text-blue-700 bg-blue-50' : 'text-purple-700 bg-purple-50'}> {complexityInfo.level === 1 ? '⚡' : complexityInfo.level === 2 ? '🔗' : '🧠'} {complexityInfo.name} </span> </div> <!-- Tags --> {skill.tags.length > 0 && ( <div class=" flex flex-wrap gap-1.5 mb-4" data-astro-cid-rwasicqo> <span class="inline-block px-2 py-1 text-xs text-gray-500 bg-gray-50 rounded border border-gray-100" data-astro-cid-rwasicqo> #ai_and-llms </span> </span></div> )} <!-- Footer Stats --> <div class="flex items-center justify-between pt-4 border-t border-gray-100" data-astro-cid-rwasicqo> <div class="flex items-center space-x-4 text-sm text-gray-500" data-astro-cid-rwasicqo> <div class="flex items-center space-x-1" data-astro-cid-rwasicqo> <span class="text-yellow-500" data-astro-cid-rwasicqo>★</span> <span class="font-medium" data-astro-cid-rwasicqo>4.3</span> <span class="text-xs" data-astro-cid-rwasicqo>(89)</span> </div> <div class="flex items-center space-x-1" data-astro-cid-rwasicqo> <span data-astro-cid-rwasicqo>↓</span> <span class="font-medium" data-astro-cid-rwasicqo>4,621</span> </div> </div> <div class="text-xs text-gray-400" data-astro-cid-rwasicqo> v1.0.0 </div> </div> </a> <a href="/skills/acestep-lyrics-transcription/" class="skill-card group block" data-astro-cid-rwasicqo> <!-- Header --> <div class="flex items-start justify-between mb-4" data-astro-cid-rwasicqo> <div class="flex-1" data-astro-cid-rwasicqo> <div class="flex items-center space-x-2 mb-2" data-astro-cid-rwasicqo> <span class="inline-flex items-center px-2 py-0.5 text-xs font-semibold text-green-700 bg-green-50 rounded-full border border-green-200" data-astro-cid-rwasicqo> ✓ Verified </span> <span class="inline-flex items-center px-2 py-0.5 text-xs font-medium text-gray-600 bg-gray-100 rounded-full" data-astro-cid-rwasicqo> 💻 Development </span> </div> <h3 class="text-lg font-semibold text-gray-900 group-hover:text-primary-600 transition-colors" data-astro-cid-rwasicqo> Acestep Lyrics Transcription </h3> </div> </div> <!-- Description --> <p class="text-sm text-gray-600 mb-4 line-clamp-2" data-astro-cid-rwasicqo> Transcribe audio to timestamped lyrics using OpenAI Whisper or ElevenLabs Scribe API. </p> <!-- Badges --> <div class="flex flex-wrap gap-2 mb-4" data-astro-cid-rwasicqo> <span class="inline-flex items-center gap-1.5 px-2.5 py-1 text-xs font-medium rounded-lg bg-green-50 text-emerald-700 border border-emerald-200 hover:bg-green-100 transition-colors" title="Works best with GPT-4 and GPT-4 Turbo" data-astro-cid-3xlfahoe> <span data-astro-cid-3xlfahoe>⚡</span> <span data-astro-cid-3xlfahoe>GPT-Optimized</span> </span> <span class="inline-flex items-center px-2.5 py-1 text-xs font-medium rounded-lg class={complexityInfo.level === 1 ? 'text-green-700 bg-green-50' : complexityInfo.level === 2 ? 'text-blue-700 bg-blue-50' : 'text-purple-700 bg-purple-50'}> {complexityInfo.level === 1 ? '⚡' : complexityInfo.level === 2 ? '🔗' : '🧠'} {complexityInfo.name} </span> </div> <!-- Tags --> {skill.tags.length > 0 && ( <div class=" flex flex-wrap gap-1.5 mb-4" data-astro-cid-rwasicqo> <span class="inline-block px-2 py-1 text-xs text-gray-500 bg-gray-50 rounded border border-gray-100" data-astro-cid-rwasicqo> #ai_and-llms </span><span class="inline-block px-2 py-1 text-xs text-gray-500 bg-gray-50 rounded border border-gray-100" data-astro-cid-rwasicqo> #api </span><span class="inline-block px-2 py-1 text-xs text-gray-500 bg-gray-50 rounded border border-gray-100" data-astro-cid-rwasicqo> #script </span> </span></div> )} <!-- Footer Stats --> <div class="flex items-center justify-between pt-4 border-t border-gray-100" data-astro-cid-rwasicqo> <div class="flex items-center space-x-4 text-sm text-gray-500" data-astro-cid-rwasicqo> <div class="flex items-center space-x-1" data-astro-cid-rwasicqo> <span class="text-yellow-500" data-astro-cid-rwasicqo>★</span> <span class="font-medium" data-astro-cid-rwasicqo>3.8</span> <span class="text-xs" data-astro-cid-rwasicqo>(274)</span> </div> <div class="flex items-center space-x-1" data-astro-cid-rwasicqo> <span data-astro-cid-rwasicqo>↓</span> <span class="font-medium" data-astro-cid-rwasicqo>17,648</span> </div> </div> <div class="text-xs text-gray-400" data-astro-cid-rwasicqo> v1.0.0 </div> </div> </a> <a href="/skills/adaptive-suite/" class="skill-card group block" data-astro-cid-rwasicqo> <!-- Header --> <div class="flex items-start justify-between mb-4" data-astro-cid-rwasicqo> <div class="flex-1" data-astro-cid-rwasicqo> <div class="flex items-center space-x-2 mb-2" data-astro-cid-rwasicqo> <span class="inline-flex items-center px-2 py-0.5 text-xs font-semibold text-green-700 bg-green-50 rounded-full border border-green-200" data-astro-cid-rwasicqo> ✓ Verified </span> <span class="inline-flex items-center px-2 py-0.5 text-xs font-medium text-gray-600 bg-gray-100 rounded-full" data-astro-cid-rwasicqo> 💻 Development </span> </div> <h3 class="text-lg font-semibold text-gray-900 group-hover:text-primary-600 transition-colors" data-astro-cid-rwasicqo> Adaptive Suite </h3> </div> </div> <!-- Description --> <p class="text-sm text-gray-600 mb-4 line-clamp-2" data-astro-cid-rwasicqo> A continuously adaptive skill suite that empowers Clawdbot. </p> <!-- Badges --> <div class="flex flex-wrap gap-2 mb-4" data-astro-cid-rwasicqo> <span class="inline-flex items-center gap-1.5 px-2.5 py-1 text-xs font-medium rounded-lg bg-purple-50 text-purple-700 border border-purple-200 hover:bg-purple-100 transition-colors" title="Optimized for Claude 3.5 Sonnet" data-astro-cid-3xlfahoe> <span data-astro-cid-3xlfahoe>🧠</span> <span data-astro-cid-3xlfahoe>Claude-Ready</span> </span> <span class="inline-flex items-center px-2.5 py-1 text-xs font-medium rounded-lg class={complexityInfo.level === 1 ? 'text-green-700 bg-green-50' : complexityInfo.level === 2 ? 'text-blue-700 bg-blue-50' : 'text-purple-700 bg-purple-50'}> {complexityInfo.level === 1 ? '⚡' : complexityInfo.level === 2 ? '🔗' : '🧠'} {complexityInfo.name} </span> </div> <!-- Tags --> {skill.tags.length > 0 && ( <div class=" flex flex-wrap gap-1.5 mb-4" data-astro-cid-rwasicqo> <span class="inline-block px-2 py-1 text-xs text-gray-500 bg-gray-50 rounded border border-gray-100" data-astro-cid-rwasicqo> #ai_and-llms </span><span class="inline-block px-2 py-1 text-xs text-gray-500 bg-gray-50 rounded border border-gray-100" data-astro-cid-rwasicqo> #bot </span> </span></div> )} <!-- Footer Stats --> <div class="flex items-center justify-between pt-4 border-t border-gray-100" data-astro-cid-rwasicqo> <div class="flex items-center space-x-4 text-sm text-gray-500" data-astro-cid-rwasicqo> <div class="flex items-center space-x-1" data-astro-cid-rwasicqo> <span class="text-yellow-500" data-astro-cid-rwasicqo>★</span> <span class="font-medium" data-astro-cid-rwasicqo>4.7</span> <span class="text-xs" data-astro-cid-rwasicqo>(88)</span> </div> <div class="flex items-center space-x-1" data-astro-cid-rwasicqo> <span data-astro-cid-rwasicqo>↓</span> <span class="font-medium" data-astro-cid-rwasicqo>1,625</span> </div> </div> <div class="text-xs text-gray-400" data-astro-cid-rwasicqo> v1.0.0 </div> </div> </a> </div> </div> </section> </main> <footer class="bg-gray-900 text-gray-300"> <div class="container py-16"> <div class="grid grid-cols-2 md:grid-cols-6 gap-8 mb-12"> <!-- Brand Column --> <div class="col-span-2"> <a href="/" class="flex items-center mb-4"> <!-- SVG Logo --> <img src="/logo.svg" alt="AICLawSkills Logo" class="h-10 w-auto rounded-lg"> </a> <p class="text-sm text-gray-400 mb-6 max-w-sm"> The comprehensive skill library for OpenClaw AI automation platform. Explore verified skills and boost your productivity. </p> <!-- Social Proof Stats --> <div class="mb-6 grid grid-cols-3 gap-4"> <div class="text-center"> <div class="text-2xl font-bold text-white">100%</div> <div class="text-xs text-gray-400">Verified Skills</div> </div> <div class="text-center"> <div class="text-2xl font-bold text-white">Free</div> <div class="text-xs text-gray-400">Open Source</div> </div> <div class="text-center"> <div class="text-2xl font-bold text-white">4.8★</div> <div class="text-xs text-gray-400">User Rating</div> </div> </div> <!-- Trust Badges --> <div class="flex flex-wrap gap-3 mb-6"> <div class="flex items-center gap-2 text-xs text-gray-400 bg-gray-800 px-3 py-1 rounded-full"> <span class="text-green-400">✓</span> 100% Verified </div> <div class="flex items-center gap-2 text-xs text-gray-400 bg-gray-800 px-3 py-1 rounded-full"> <span class="text-blue-400">🛡️</span> Security Audited </div> <div class="flex items-center gap-2 text-xs text-gray-400 bg-gray-800 px-3 py-1 rounded-full"> <span class="text-purple-400">⚡</span> Updated Weekly </div> </div> <div class="flex space-x-4"> <a href="https://github.com" class="text-gray-400 hover:text-white transition-colors" aria-label="GitHub"> <svg class="h-5 w-5" fill="currentColor" viewBox="0 0 24 24"> <path fill-rule="evenodd" d="M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z" clip-rule="evenodd"></path> </svg> </a> <a href="https://twitter.com" class="text-gray-400 hover:text-white transition-colors" aria-label="Twitter"> <svg class="h-5 w-5" fill="currentColor" viewBox="0 0 24 24"> <path d="M8.29 20.251c7.547 0 11.675-6.253 11.675-11.675 0-.178 0-.355-.012-.53A8.348 8.348 0 0022 5.92a8.19 8.19 0 01-2.357.646 4.118 4.118 0 001.804-2.27 8.224 8.224 0 01-2.605.996 4.107 4.107 0 00-6.993 3.743 11.65 11.65 0 01-8.457-4.287 4.106 4.106 0 001.27 5.477A4.072 4.072 0 012.8 9.713v.052a4.105 4.105 0 003.292 4.022 4.095 4.095 0 01-1.853.07 4.108 4.108 0 003.834 2.85A8.233 8.233 0 012 18.407a11.616 11.616 0 006.29 1.84"></path> </svg> </a> </div> </div> <!-- Product Links --> <div> <h3 class="text-sm font-semibold text-white uppercase tracking-wider mb-4">Product</h3> <ul class="space-y-3"> <li> <a href="/skills/" class="text-sm text-gray-400 hover:text-primary-400 transition-colors"> All Skills </a> </li><li> <a href="/skills/#categories" class="text-sm text-gray-400 hover:text-primary-400 transition-colors"> Browse by Category </a> </li><li> <a href="/skill-bundles/" class="text-sm text-gray-400 hover:text-primary-400 transition-colors"> Skill Bundles </a> </li><li> <a href="/skills/category/web-scrapers" class="text-sm text-gray-400 hover:text-primary-400 transition-colors"> Web Scrapers </a> </li><li> <a href="/skills/category/ecommerce" class="text-sm text-gray-400 hover:text-primary-400 transition-colors"> E-commerce </a> </li><li> <a href="/skills/category/social-media" class="text-sm text-gray-400 hover:text-primary-400 transition-colors"> Social Media </a> </li><li> <a href="/skills/category/development" class="text-sm text-gray-400 hover:text-primary-400 transition-colors"> Development </a> </li> </ul> </div> <!-- Resources Links --> <div> <h3 class="text-sm font-semibold text-white uppercase tracking-wider mb-4">Resources</h3> <ul class="space-y-3"> <li> <a href="/get-started/" class="text-sm text-gray-400 hover:text-primary-400 transition-colors"> Documentation </a> </li><li> <a href="/get-started/installation" class="text-sm text-gray-400 hover:text-primary-400 transition-colors"> Installation </a> </li><li> <a href="/get-started/configuration" class="text-sm text-gray-400 hover:text-primary-400 transition-colors"> Configuration </a> </li><li> <a href="/get-started/troubleshooting" class="text-sm text-gray-400 hover:text-primary-400 transition-colors"> Troubleshooting </a> </li> </ul> </div> <!-- Security Links --> <div> <h3 class="text-sm font-semibold text-white uppercase tracking-wider mb-4">🔒 Security</h3> <ul class="space-y-3"> <li> <a href="/security/" class="text-sm text-gray-400 hover:text-primary-400 transition-colors"> Security Overview </a> </li><li> <a href="/security/5-step-hardening-guide" class="text-sm text-gray-400 hover:text-primary-400 transition-colors"> 5-Step Hardening Guide </a> </li><li> <a href="/security/auth-none-dangers" class="text-sm text-gray-400 hover:text-primary-400 transition-colors"> Why auth:none is Dangerous </a> </li><li> <a href="/security/tailscale-guide" class="text-sm text-gray-400 hover:text-primary-400 transition-colors"> Tailscale Setup Guide </a> </li> </ul> </div> <!-- Use Cases --> <div> <h3 class="text-sm font-semibold text-white uppercase tracking-wider mb-4">Use Cases</h3> <ul class="space-y-3"> <li> <a href="/use-cases/ecommerce" class="text-sm text-gray-400 hover:text-primary-400 transition-colors flex items-center"> <span class="mr-2">🛒</span> E-commerce </a> </li><li> <a href="/use-cases/development" class="text-sm text-gray-400 hover:text-primary-400 transition-colors flex items-center"> <span class="mr-2">💻</span> Development </a> </li><li> <a href="/use-cases/content-creation" class="text-sm text-gray-400 hover:text-primary-400 transition-colors flex items-center"> <span class="mr-2">📝</span> Content Creation </a> </li> </ul> </div> </div> <!-- Comparisons Section --> <div class="border-t border-gray-800 pt-8 mb-8"> <h3 class="text-sm font-semibold text-white uppercase tracking-wider mb-4">Comparisons</h3> <div class="flex flex-wrap gap-6"> <a href="/comparisons/" class="text-sm text-gray-400 hover:text-primary-400 transition-colors"> Comparisons </a><a href="/comparisons/skill-comparison/" class="text-sm text-gray-400 hover:text-primary-400 transition-colors"> Skill Comparison </a><a href="/comparisons/cost-comparison/" class="text-sm text-gray-400 hover:text-primary-400 transition-colors"> Cost Analysis </a><a href="/comparisons/architecture-comparison/" class="text-sm text-gray-400 hover:text-primary-400 transition-colors"> Architecture </a><a href="/tools/benchmarks/" class="text-sm text-gray-400 hover:text-primary-400 transition-colors"> Benchmarks </a><a href="/tools/hardware/" class="text-sm text-gray-400 hover:text-primary-400 transition-colors"> Hardware </a> </div> </div> <!-- Bottom Bar --> <div class="border-t border-gray-800 pt-8 flex flex-col md:flex-row justify-between items-center space-y-4 md:space-y-0"> <p class="text-sm text-gray-400"> © 2026 AICLawSkills. All rights reserved. </p> <div class="flex space-x-6"> <a href="/legal/about" class="text-sm text-gray-400 hover:text-white transition-colors"> About </a><a href="/legal/privacy" class="text-sm text-gray-400 hover:text-white transition-colors"> Privacy Policy </a><a href="/legal/terms" class="text-sm text-gray-400 hover:text-white transition-colors"> Terms of Service </a><a href="/legal/contact" class="text-sm text-gray-400 hover:text-white transition-colors"> Contact </a> </div> </div> </div> </footer> <div id="search-backdrop" class="search-backdrop hidden fixed inset-0 bg-black/50 z-50 transition-opacity" data-astro-cid-2eu6zh2g></div> <div id="search-modal" class="search-modal hidden fixed inset-0 z-50 flex items-start justify-center pt-[15vh] px-4" data-astro-cid-2eu6zh2g> <div class="relative w-full max-w-2xl bg-white rounded-xl shadow-2xl border border-gray-200 overflow-hidden" data-astro-cid-2eu6zh2g> <!-- Search Input --> <div class="flex items-center px-4 py-3 border-b border-gray-200" data-astro-cid-2eu6zh2g> <svg class="w-5 h-5 text-gray-400 mr-3" fill="none" stroke="currentColor" viewBox="0 0 24 24" data-astro-cid-2eu6zh2g> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" data-astro-cid-2eu6zh2g></path> </svg> <input id="search-input" type="text" placeholder="Search skills... (e.g., 'shopify', 'email', 'automation')" class="flex-1 outline-none text-gray-900 placeholder-gray-400" data-astro-cid-2eu6zh2g> <div class="flex items-center gap-2 ml-2" data-astro-cid-2eu6zh2g> <kbd class="hidden sm:inline-block px-2 py-1 text-xs font-semibold text-gray-400 bg-gray-100 border border-gray-200 rounded" data-astro-cid-2eu6zh2g>ESC</kbd> </div> </div> <!-- Search Results --> <div id="search-results" class="max-h-[50vh] overflow-y-auto" data-astro-cid-2eu6zh2g> <!-- Empty State --> <div id="search-empty" class="px-4 py-8 text-center text-gray-500" data-astro-cid-2eu6zh2g> <svg class="w-12 h-12 mx-auto mb-3 text-gray-300" fill="none" stroke="currentColor" viewBox="0 0 24 24" data-astro-cid-2eu6zh2g> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" data-astro-cid-2eu6zh2g></path> </svg> <p class="text-sm font-medium" data-astro-cid-2eu6zh2g>Start typing to search skills</p> <p class="text-xs mt-1 text-gray-400" data-astro-cid-2eu6zh2g>Search by name, category, or tags</p> </div> <!-- Results will be injected here --> <div id="search-results-list" class="py-2 hidden" data-astro-cid-2eu6zh2g></div> </div> <!-- Footer --> <div class="px-4 py-2 border-t border-gray-200 bg-gray-50 flex items-center justify-between text-xs text-gray-500" data-astro-cid-2eu6zh2g> <div class="flex items-center gap-3" data-astro-cid-2eu6zh2g> <span class="flex items-center gap-1" data-astro-cid-2eu6zh2g> <kbd data-astro-cid-2eu6zh2g>↑</kbd><kbd data-astro-cid-2eu6zh2g>↓</kbd> to navigate </span> <span class="flex items-center gap-1" data-astro-cid-2eu6zh2g> <kbd data-astro-cid-2eu6zh2g>↵</kbd> to select </span> </div> <span id="search-count" data-astro-cid-2eu6zh2g>0 results</span> </div> </div> </div> <script> // Skills data will be injected server-side window.SKILLS_DATA = []; </script> </body></html>