microsoft-todo-cli 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. microsoft_todo_cli-1.0.0/CHANGES.txt +10 -0
  2. microsoft_todo_cli-1.0.0/LICENSE +22 -0
  3. microsoft_todo_cli-1.0.0/MANIFEST.in +4 -0
  4. microsoft_todo_cli-1.0.0/PKG-INFO +296 -0
  5. microsoft_todo_cli-1.0.0/README.md +258 -0
  6. microsoft_todo_cli-1.0.0/docs/setup-api.md +67 -0
  7. microsoft_todo_cli-1.0.0/microsoft_todo_cli.egg-info/PKG-INFO +296 -0
  8. microsoft_todo_cli-1.0.0/microsoft_todo_cli.egg-info/SOURCES.txt +43 -0
  9. microsoft_todo_cli-1.0.0/microsoft_todo_cli.egg-info/dependency_links.txt +1 -0
  10. microsoft_todo_cli-1.0.0/microsoft_todo_cli.egg-info/entry_points.txt +2 -0
  11. microsoft_todo_cli-1.0.0/microsoft_todo_cli.egg-info/requires.txt +3 -0
  12. microsoft_todo_cli-1.0.0/microsoft_todo_cli.egg-info/top_level.txt +2 -0
  13. microsoft_todo_cli-1.0.0/setup.cfg +4 -0
  14. microsoft_todo_cli-1.0.0/setup.py +42 -0
  15. microsoft_todo_cli-1.0.0/tests/__init__.py +0 -0
  16. microsoft_todo_cli-1.0.0/tests/run_tests.py +39 -0
  17. microsoft_todo_cli-1.0.0/tests/test_checklist_cli.py +118 -0
  18. microsoft_todo_cli-1.0.0/tests/test_checklist_item_model.py +108 -0
  19. microsoft_todo_cli-1.0.0/tests/test_checklist_wrapper.py +62 -0
  20. microsoft_todo_cli-1.0.0/tests/test_cli_commands.py +436 -0
  21. microsoft_todo_cli-1.0.0/tests/test_cli_output.py +169 -0
  22. microsoft_todo_cli-1.0.0/tests/test_cli_url_integration.py +136 -0
  23. microsoft_todo_cli-1.0.0/tests/test_datetime_parser.py +233 -0
  24. microsoft_todo_cli-1.0.0/tests/test_filters.py +120 -0
  25. microsoft_todo_cli-1.0.0/tests/test_json_output.py +223 -0
  26. microsoft_todo_cli-1.0.0/tests/test_lst_output.py +135 -0
  27. microsoft_todo_cli-1.0.0/tests/test_models.py +235 -0
  28. microsoft_todo_cli-1.0.0/tests/test_odata_escape.py +175 -0
  29. microsoft_todo_cli-1.0.0/tests/test_recurrence.py +159 -0
  30. microsoft_todo_cli-1.0.0/tests/test_update_command.py +192 -0
  31. microsoft_todo_cli-1.0.0/tests/test_utils.py +186 -0
  32. microsoft_todo_cli-1.0.0/tests/test_wrapper.py +191 -0
  33. microsoft_todo_cli-1.0.0/todocli/__init__.py +1 -0
  34. microsoft_todo_cli-1.0.0/todocli/cli.py +1356 -0
  35. microsoft_todo_cli-1.0.0/todocli/graphapi/__init__.py +0 -0
  36. microsoft_todo_cli-1.0.0/todocli/graphapi/oauth.py +136 -0
  37. microsoft_todo_cli-1.0.0/todocli/graphapi/wrapper.py +660 -0
  38. microsoft_todo_cli-1.0.0/todocli/models/__init__.py +0 -0
  39. microsoft_todo_cli-1.0.0/todocli/models/checklistitem.py +59 -0
  40. microsoft_todo_cli-1.0.0/todocli/models/todolist.py +27 -0
  41. microsoft_todo_cli-1.0.0/todocli/models/todotask.py +105 -0
  42. microsoft_todo_cli-1.0.0/todocli/utils/__init__.py +0 -0
  43. microsoft_todo_cli-1.0.0/todocli/utils/datetime_util.py +321 -0
  44. microsoft_todo_cli-1.0.0/todocli/utils/recurrence_util.py +122 -0
  45. microsoft_todo_cli-1.0.0/todocli/utils/update_checker.py +55 -0
@@ -0,0 +1,10 @@
1
+ v1.0.0, 2026-02-04
2
+ - Fork from kiblee/tod0 with redesigned CLI
3
+ - Removed interactive TUI, CLI-only
4
+ - Added JSON output for all commands (--json flag)
5
+ - Added --id flag for stable task identification
6
+ - Added filters: --all, --completed, --due-today, --overdue, --important
7
+ - Added uncomplete/uncomplete-step commands
8
+ - Added inline step creation with -S flag
9
+ - Renamed commands: lists (was ls), tasks (was lst), new-list (was newl)
10
+ - Added command aliases: t, n, c, d
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2019 kiblee
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
@@ -0,0 +1,4 @@
1
+ include README.md
2
+ include LICENSE
3
+ include CHANGES.txt
4
+ recursive-include docs *.md
@@ -0,0 +1,296 @@
1
+ Metadata-Version: 2.4
2
+ Name: microsoft-todo-cli
3
+ Version: 1.0.0
4
+ Summary: Fast, minimal command-line client for Microsoft To-Do
5
+ Home-page: https://github.com/underwear/microsoft-todo-cli
6
+ Author: underwear
7
+ Author-email:
8
+ License: MIT
9
+ Keywords: microsoft todo cli task management
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Environment :: Console
12
+ Classifier: Intended Audience :: End Users/Desktop
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Topic :: Utilities
21
+ Requires-Python: >=3.10
22
+ Description-Content-Type: text/markdown
23
+ License-File: LICENSE
24
+ Requires-Dist: pyyaml
25
+ Requires-Dist: requests>=2.28.1
26
+ Requires-Dist: requests_oauthlib
27
+ Dynamic: author
28
+ Dynamic: classifier
29
+ Dynamic: description
30
+ Dynamic: description-content-type
31
+ Dynamic: home-page
32
+ Dynamic: keywords
33
+ Dynamic: license
34
+ Dynamic: license-file
35
+ Dynamic: requires-dist
36
+ Dynamic: requires-python
37
+ Dynamic: summary
38
+
39
+ # microsoft-todo-cli
40
+
41
+ Fast, minimal command-line client for Microsoft To-Do
42
+
43
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
44
+ [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
45
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
46
+
47
+ ```
48
+ $ todo tasks
49
+ [0] Buy groceries
50
+ [1] Call mom ! (due: tomorrow)
51
+ [2] Review PR #42
52
+ [x] Check tests
53
+ [ ] Add documentation
54
+
55
+ $ todo new "Deploy v2.0" -d friday -r 9am -I
56
+ Created task 'Deploy v2.0' in 'Tasks'
57
+
58
+ $ todo complete 0
59
+ Completed task 'Buy groceries' in 'Tasks'
60
+ ```
61
+
62
+ ## Install
63
+
64
+ **Requirements:** Python 3.10+
65
+
66
+ ```bash
67
+ pip install microsoft-todo-cli
68
+ ```
69
+
70
+ Or install from source:
71
+
72
+ ```bash
73
+ git clone https://github.com/underwear/microsoft-todo-cli.git
74
+ cd microsoft-todo-cli
75
+ pip install -e .
76
+ ```
77
+
78
+ Then configure Microsoft API access: **[Setup Guide](docs/setup-api.md)** (5 min)
79
+
80
+ ## Quick Start
81
+
82
+ ```bash
83
+ todo lists # Show all lists
84
+ todo tasks # Show tasks from default list
85
+ todo tasks Work # Show tasks from "Work" list
86
+ todo new "Buy milk" # Create task
87
+ todo complete "Buy milk" # Mark done (or: todo c "Buy milk")
88
+ todo rm "Old task" # Delete
89
+ ```
90
+
91
+ **Default list**: The first list returned by Microsoft To-Do API (usually "Tasks"). Specify a list explicitly with `-l ListName` or as a positional argument.
92
+
93
+ **Short aliases**: `t` (tasks), `n` (new), `c` (complete), `d` (rm) — see [Aliases](#aliases).
94
+
95
+ ## Usage
96
+
97
+ ### Tasks
98
+
99
+ ```bash
100
+ # View
101
+ todo tasks # Default list
102
+ todo tasks Work # Specific list
103
+ todo tasks --due-today # Due today
104
+ todo tasks --overdue # Past due
105
+ todo tasks --important # High priority
106
+ todo tasks --completed # Done tasks
107
+ todo tasks --all # Everything
108
+
109
+ # Create
110
+ todo new "Task name" # Basic
111
+ todo new "Task" -l Work # In specific list
112
+ todo new "Task" -d tomorrow # With due date
113
+ todo new "Task" -r 2h # With reminder (in 2 hours)
114
+ todo new "Task" -d mon -r 9am # Due Monday, remind at 9am
115
+ todo new "Task" -I # Important
116
+ todo new "Task" -R daily # Recurring
117
+ todo new "Task" -R weekly:mon,fri # Recurring on specific days
118
+ todo new "Task" -S "Step 1" -S "Step 2" # With subtasks
119
+
120
+ # View single task
121
+ todo show "Task" # Show task details
122
+ todo show 0 # Show by index
123
+
124
+ # Manage
125
+ todo complete "Task" # Mark complete
126
+ todo complete 0 1 2 # Complete by index (batch)
127
+ todo uncomplete "Task" # Reopen task
128
+ todo update "Task" --title "New" # Rename
129
+ todo update "Task" -d friday -I # Change due date, make important
130
+ todo rm "Task" # Delete (asks confirmation)
131
+ todo rm "Task" -y # Delete (no confirmation)
132
+ ```
133
+
134
+ ### Subtasks (Steps)
135
+
136
+ ```bash
137
+ todo new-step "Task" "Step text" # Add step
138
+ todo list-steps "Task" # List steps
139
+ todo complete-step "Task" "Step" # Check off
140
+ todo uncomplete-step "Task" "Step" # Uncheck
141
+ todo rm-step "Task" 0 # Remove by index
142
+ ```
143
+
144
+ ### Lists
145
+
146
+ ```bash
147
+ todo lists # Show all lists
148
+ todo new-list "Project X" # Create list
149
+ todo rename-list "Old" "New" # Rename list
150
+ todo rm-list "Project X" # Delete list (asks confirmation)
151
+ todo rm-list "Project X" -y # Delete list (no confirmation)
152
+ ```
153
+
154
+ ### Date & Time Formats
155
+
156
+ | Type | Examples |
157
+ |------|----------|
158
+ | Relative | `1h`, `30m`, `2d`, `1h30m` |
159
+ | Time | `9:30`, `9am`, `17:00`, `5:30pm` |
160
+ | Days | `tomorrow`, `monday`, `fri` |
161
+ | Date | `2026-12-31`, `31.12.2026`, `12/31/2026` |
162
+ | Keywords | `morning` (7:00), `evening` (18:00) |
163
+
164
+ ### Recurrence Patterns
165
+
166
+ | Pattern | Description |
167
+ |---------|-------------|
168
+ | `daily` | Every day |
169
+ | `weekly` | Every week |
170
+ | `monthly` | Every month |
171
+ | `yearly` | Every year |
172
+ | `weekdays` | Monday to Friday |
173
+ | `weekly:mon,wed,fri` | Specific days |
174
+ | `every 2 days` | Custom interval |
175
+ | `every 3 weeks` | Custom interval |
176
+
177
+ ## Scripting & Automation
178
+
179
+ ### JSON Output
180
+
181
+ Add `--json` to any command for machine-readable output:
182
+
183
+ ```bash
184
+ todo tasks --json
185
+ todo lists --json
186
+ todo show "Task" --json
187
+ ```
188
+
189
+ **Example: `todo tasks --json`**
190
+ ```json
191
+ {
192
+ "list": "Tasks",
193
+ "tasks": [
194
+ {
195
+ "id": "AAMkADU3...",
196
+ "title": "Buy groceries",
197
+ "status": "notStarted",
198
+ "importance": "normal",
199
+ "due_date": null,
200
+ "reminder": null,
201
+ "recurrence": null,
202
+ "steps": []
203
+ },
204
+ {
205
+ "id": "AAMkADU4...",
206
+ "title": "Call mom",
207
+ "status": "notStarted",
208
+ "importance": "high",
209
+ "due_date": "2026-02-06",
210
+ "reminder": "2026-02-06T09:00:00",
211
+ "recurrence": null,
212
+ "steps": [
213
+ {"id": "step1", "name": "Check tests", "completed": true},
214
+ {"id": "step2", "name": "Add documentation", "completed": false}
215
+ ]
216
+ }
217
+ ]
218
+ }
219
+ ```
220
+
221
+ **Write commands return action confirmation:**
222
+ ```bash
223
+ todo new "Task" --json # {"action": "created", "id": "AAMk...", "title": "Task", "list": "Tasks"}
224
+ todo complete "Task" --json # {"action": "completed", "id": "AAMk...", "title": "Task", "list": "Tasks"}
225
+ todo rm "Task" -y --json # {"action": "removed", "id": "AAMk...", "title": "Task", "list": "Tasks"}
226
+ ```
227
+
228
+ ### Task Identification
229
+
230
+ Tasks can be identified by **name**, **index**, or **ID**. Priority for reliable automation:
231
+
232
+ | Method | Stability | Use case |
233
+ |--------|-----------|----------|
234
+ | `--id "AAMk..."` | Stable | Scripts, automation, agents |
235
+ | Index (`0`, `1`) | Unstable | Interactive use only |
236
+ | Name (`"Task"`) | Unstable | Interactive use, unique names |
237
+
238
+ ```bash
239
+ # Get task ID from JSON output
240
+ todo tasks --json | jq -r '.tasks[0].id'
241
+
242
+ # Show IDs inline (human-readable + IDs)
243
+ todo tasks --show-id
244
+
245
+ # Use ID in commands (requires -l for list context)
246
+ todo complete --id "AAMkADU3..." -l Tasks
247
+ todo update --id "AAMkADU3..." --title "New title"
248
+ todo rm --id "AAMkADU3..." -l Tasks -y
249
+ ```
250
+
251
+ **Example: Create and complete a task by ID**
252
+ ```bash
253
+ ID=$(todo new "Deploy v2.0" -l Work --json | jq -r '.id')
254
+ # ... later ...
255
+ todo complete --id "$ID" -l Work
256
+ ```
257
+
258
+ ### Exit Codes
259
+
260
+ | Code | Meaning |
261
+ |------|---------|
262
+ | `0` | Success |
263
+ | `1` | General error (invalid arguments, task not found, API error) |
264
+
265
+ With `--json`: stdout contains only valid JSON on success. Errors go to stderr.
266
+
267
+ ### Tips for Scripts and Agents
268
+
269
+ - **Prefer `--id` over names/indexes**: Names can have duplicates (first match wins). Indexes change as tasks are added/completed/reordered.
270
+ - **Always use `-l ListName`** with `--id` to specify list context.
271
+ - **Capture IDs on creation**: Store the ID from `todo new --json` for later operations.
272
+ - **Use `--json` for parsing**: Human-readable output format may change between versions.
273
+ - **Use `-y` flag** with `rm` commands to skip confirmation prompts.
274
+
275
+ ## Aliases
276
+
277
+ | Alias | Command | Alias | Command |
278
+ |-------|---------|-------|---------|
279
+ | `t` | `tasks` | `d` | `rm` |
280
+ | `n` | `new` | `newl` | `new-list` |
281
+ | `c` | `complete` | `reopen` | `uncomplete` |
282
+
283
+ ```bash
284
+ todo t # = todo tasks
285
+ todo n "Task" -d fri # = todo new "Task" -d fri
286
+ todo c 0 1 2 # = todo complete 0 1 2
287
+ todo d "Old" -y # = todo rm "Old" -y
288
+ ```
289
+
290
+ ## Credits
291
+
292
+ Forked from [kiblee/tod0](https://github.com/kiblee/tod0) with a redesigned CLI.
293
+
294
+ ## License
295
+
296
+ MIT
@@ -0,0 +1,258 @@
1
+ # microsoft-todo-cli
2
+
3
+ Fast, minimal command-line client for Microsoft To-Do
4
+
5
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
6
+ [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
7
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
8
+
9
+ ```
10
+ $ todo tasks
11
+ [0] Buy groceries
12
+ [1] Call mom ! (due: tomorrow)
13
+ [2] Review PR #42
14
+ [x] Check tests
15
+ [ ] Add documentation
16
+
17
+ $ todo new "Deploy v2.0" -d friday -r 9am -I
18
+ Created task 'Deploy v2.0' in 'Tasks'
19
+
20
+ $ todo complete 0
21
+ Completed task 'Buy groceries' in 'Tasks'
22
+ ```
23
+
24
+ ## Install
25
+
26
+ **Requirements:** Python 3.10+
27
+
28
+ ```bash
29
+ pip install microsoft-todo-cli
30
+ ```
31
+
32
+ Or install from source:
33
+
34
+ ```bash
35
+ git clone https://github.com/underwear/microsoft-todo-cli.git
36
+ cd microsoft-todo-cli
37
+ pip install -e .
38
+ ```
39
+
40
+ Then configure Microsoft API access: **[Setup Guide](docs/setup-api.md)** (5 min)
41
+
42
+ ## Quick Start
43
+
44
+ ```bash
45
+ todo lists # Show all lists
46
+ todo tasks # Show tasks from default list
47
+ todo tasks Work # Show tasks from "Work" list
48
+ todo new "Buy milk" # Create task
49
+ todo complete "Buy milk" # Mark done (or: todo c "Buy milk")
50
+ todo rm "Old task" # Delete
51
+ ```
52
+
53
+ **Default list**: The first list returned by Microsoft To-Do API (usually "Tasks"). Specify a list explicitly with `-l ListName` or as a positional argument.
54
+
55
+ **Short aliases**: `t` (tasks), `n` (new), `c` (complete), `d` (rm) — see [Aliases](#aliases).
56
+
57
+ ## Usage
58
+
59
+ ### Tasks
60
+
61
+ ```bash
62
+ # View
63
+ todo tasks # Default list
64
+ todo tasks Work # Specific list
65
+ todo tasks --due-today # Due today
66
+ todo tasks --overdue # Past due
67
+ todo tasks --important # High priority
68
+ todo tasks --completed # Done tasks
69
+ todo tasks --all # Everything
70
+
71
+ # Create
72
+ todo new "Task name" # Basic
73
+ todo new "Task" -l Work # In specific list
74
+ todo new "Task" -d tomorrow # With due date
75
+ todo new "Task" -r 2h # With reminder (in 2 hours)
76
+ todo new "Task" -d mon -r 9am # Due Monday, remind at 9am
77
+ todo new "Task" -I # Important
78
+ todo new "Task" -R daily # Recurring
79
+ todo new "Task" -R weekly:mon,fri # Recurring on specific days
80
+ todo new "Task" -S "Step 1" -S "Step 2" # With subtasks
81
+
82
+ # View single task
83
+ todo show "Task" # Show task details
84
+ todo show 0 # Show by index
85
+
86
+ # Manage
87
+ todo complete "Task" # Mark complete
88
+ todo complete 0 1 2 # Complete by index (batch)
89
+ todo uncomplete "Task" # Reopen task
90
+ todo update "Task" --title "New" # Rename
91
+ todo update "Task" -d friday -I # Change due date, make important
92
+ todo rm "Task" # Delete (asks confirmation)
93
+ todo rm "Task" -y # Delete (no confirmation)
94
+ ```
95
+
96
+ ### Subtasks (Steps)
97
+
98
+ ```bash
99
+ todo new-step "Task" "Step text" # Add step
100
+ todo list-steps "Task" # List steps
101
+ todo complete-step "Task" "Step" # Check off
102
+ todo uncomplete-step "Task" "Step" # Uncheck
103
+ todo rm-step "Task" 0 # Remove by index
104
+ ```
105
+
106
+ ### Lists
107
+
108
+ ```bash
109
+ todo lists # Show all lists
110
+ todo new-list "Project X" # Create list
111
+ todo rename-list "Old" "New" # Rename list
112
+ todo rm-list "Project X" # Delete list (asks confirmation)
113
+ todo rm-list "Project X" -y # Delete list (no confirmation)
114
+ ```
115
+
116
+ ### Date & Time Formats
117
+
118
+ | Type | Examples |
119
+ |------|----------|
120
+ | Relative | `1h`, `30m`, `2d`, `1h30m` |
121
+ | Time | `9:30`, `9am`, `17:00`, `5:30pm` |
122
+ | Days | `tomorrow`, `monday`, `fri` |
123
+ | Date | `2026-12-31`, `31.12.2026`, `12/31/2026` |
124
+ | Keywords | `morning` (7:00), `evening` (18:00) |
125
+
126
+ ### Recurrence Patterns
127
+
128
+ | Pattern | Description |
129
+ |---------|-------------|
130
+ | `daily` | Every day |
131
+ | `weekly` | Every week |
132
+ | `monthly` | Every month |
133
+ | `yearly` | Every year |
134
+ | `weekdays` | Monday to Friday |
135
+ | `weekly:mon,wed,fri` | Specific days |
136
+ | `every 2 days` | Custom interval |
137
+ | `every 3 weeks` | Custom interval |
138
+
139
+ ## Scripting & Automation
140
+
141
+ ### JSON Output
142
+
143
+ Add `--json` to any command for machine-readable output:
144
+
145
+ ```bash
146
+ todo tasks --json
147
+ todo lists --json
148
+ todo show "Task" --json
149
+ ```
150
+
151
+ **Example: `todo tasks --json`**
152
+ ```json
153
+ {
154
+ "list": "Tasks",
155
+ "tasks": [
156
+ {
157
+ "id": "AAMkADU3...",
158
+ "title": "Buy groceries",
159
+ "status": "notStarted",
160
+ "importance": "normal",
161
+ "due_date": null,
162
+ "reminder": null,
163
+ "recurrence": null,
164
+ "steps": []
165
+ },
166
+ {
167
+ "id": "AAMkADU4...",
168
+ "title": "Call mom",
169
+ "status": "notStarted",
170
+ "importance": "high",
171
+ "due_date": "2026-02-06",
172
+ "reminder": "2026-02-06T09:00:00",
173
+ "recurrence": null,
174
+ "steps": [
175
+ {"id": "step1", "name": "Check tests", "completed": true},
176
+ {"id": "step2", "name": "Add documentation", "completed": false}
177
+ ]
178
+ }
179
+ ]
180
+ }
181
+ ```
182
+
183
+ **Write commands return action confirmation:**
184
+ ```bash
185
+ todo new "Task" --json # {"action": "created", "id": "AAMk...", "title": "Task", "list": "Tasks"}
186
+ todo complete "Task" --json # {"action": "completed", "id": "AAMk...", "title": "Task", "list": "Tasks"}
187
+ todo rm "Task" -y --json # {"action": "removed", "id": "AAMk...", "title": "Task", "list": "Tasks"}
188
+ ```
189
+
190
+ ### Task Identification
191
+
192
+ Tasks can be identified by **name**, **index**, or **ID**. Priority for reliable automation:
193
+
194
+ | Method | Stability | Use case |
195
+ |--------|-----------|----------|
196
+ | `--id "AAMk..."` | Stable | Scripts, automation, agents |
197
+ | Index (`0`, `1`) | Unstable | Interactive use only |
198
+ | Name (`"Task"`) | Unstable | Interactive use, unique names |
199
+
200
+ ```bash
201
+ # Get task ID from JSON output
202
+ todo tasks --json | jq -r '.tasks[0].id'
203
+
204
+ # Show IDs inline (human-readable + IDs)
205
+ todo tasks --show-id
206
+
207
+ # Use ID in commands (requires -l for list context)
208
+ todo complete --id "AAMkADU3..." -l Tasks
209
+ todo update --id "AAMkADU3..." --title "New title"
210
+ todo rm --id "AAMkADU3..." -l Tasks -y
211
+ ```
212
+
213
+ **Example: Create and complete a task by ID**
214
+ ```bash
215
+ ID=$(todo new "Deploy v2.0" -l Work --json | jq -r '.id')
216
+ # ... later ...
217
+ todo complete --id "$ID" -l Work
218
+ ```
219
+
220
+ ### Exit Codes
221
+
222
+ | Code | Meaning |
223
+ |------|---------|
224
+ | `0` | Success |
225
+ | `1` | General error (invalid arguments, task not found, API error) |
226
+
227
+ With `--json`: stdout contains only valid JSON on success. Errors go to stderr.
228
+
229
+ ### Tips for Scripts and Agents
230
+
231
+ - **Prefer `--id` over names/indexes**: Names can have duplicates (first match wins). Indexes change as tasks are added/completed/reordered.
232
+ - **Always use `-l ListName`** with `--id` to specify list context.
233
+ - **Capture IDs on creation**: Store the ID from `todo new --json` for later operations.
234
+ - **Use `--json` for parsing**: Human-readable output format may change between versions.
235
+ - **Use `-y` flag** with `rm` commands to skip confirmation prompts.
236
+
237
+ ## Aliases
238
+
239
+ | Alias | Command | Alias | Command |
240
+ |-------|---------|-------|---------|
241
+ | `t` | `tasks` | `d` | `rm` |
242
+ | `n` | `new` | `newl` | `new-list` |
243
+ | `c` | `complete` | `reopen` | `uncomplete` |
244
+
245
+ ```bash
246
+ todo t # = todo tasks
247
+ todo n "Task" -d fri # = todo new "Task" -d fri
248
+ todo c 0 1 2 # = todo complete 0 1 2
249
+ todo d "Old" -y # = todo rm "Old" -y
250
+ ```
251
+
252
+ ## Credits
253
+
254
+ Forked from [kiblee/tod0](https://github.com/kiblee/tod0) with a redesigned CLI.
255
+
256
+ ## License
257
+
258
+ MIT
@@ -0,0 +1,67 @@
1
+ # Setting Up Microsoft API Access
2
+
3
+ To use `todo`, you need to register an application in Microsoft Azure to get API credentials.
4
+
5
+ ## Step 1: Register an Application
6
+
7
+ 1. Sign in to the [Azure Portal](https://portal.azure.com/)
8
+ 2. Navigate to **Microsoft Entra ID** (formerly Azure Active Directory)
9
+ 3. Click **Add** → **App registration**
10
+
11
+ ## Step 2: Configure the Application
12
+
13
+ Fill in the registration form:
14
+
15
+ | Field | Value |
16
+ |-------|-------|
17
+ | **Name** | `todo-cli` (or any name you prefer) |
18
+ | **Supported account types** | Accounts in any organizational directory and personal Microsoft accounts |
19
+ | **Redirect URI** | Platform: `Web`, URI: `https://localhost/login/authorized` |
20
+
21
+ Click **Register**.
22
+
23
+ ## Step 3: Note Your Client ID
24
+
25
+ After registration, you'll see the **Application (client) ID** on the overview page. Copy this value.
26
+
27
+ ## Step 4: Create a Client Secret
28
+
29
+ 1. In the left menu, click **Certificates & secrets**
30
+ 2. Click **New client secret**
31
+ 3. Add a description (e.g., "todo-cli") and choose an expiration
32
+ 4. Click **Add**
33
+ 5. **Important:** Copy the secret **Value** immediately (not the Secret ID). It won't be visible again.
34
+
35
+ ## Step 5: Configure todo
36
+
37
+ Create the config file:
38
+
39
+ ```bash
40
+ mkdir -p ~/.config/tod0
41
+ ```
42
+
43
+ Add your credentials to `~/.config/tod0/keys.yml`:
44
+
45
+ ```yaml
46
+ client_id: 'your-application-client-id'
47
+ client_secret: 'your-client-secret-value'
48
+ ```
49
+
50
+ ## Step 6: First Run
51
+
52
+ Run any command to trigger OAuth login:
53
+
54
+ ```bash
55
+ todo lists
56
+ ```
57
+
58
+ A browser window will open for Microsoft authentication. After logging in, you're ready to use the CLI.
59
+
60
+ ## Troubleshooting
61
+
62
+ **"AADSTS50011: The redirect URI specified in the request does not match"**
63
+ - Ensure the redirect URI is exactly `https://localhost/login/authorized`
64
+ - Check that platform is set to `Web`
65
+
66
+ **Token expired**
67
+ - Delete `~/.config/tod0/token.pkl` and run any command to re-authenticate