Local AI-powered task manager that integrates with Microsoft 365 via WorkIQ MCP.
TodoNess scans your Teams messages, meetings, and flagged emails to surface actionable items as suggested tasks. It provides AI coaching, follow-up drafting, and meeting prep through a web dashboard.
- Python 3.11+
- GitHub Copilot CLI installed and authenticated
- WorkIQ MCP configured for Microsoft 365 task discovery
- Cowork authenticated for drafting and approved actions
# Install dependencies and register Riveter to start at logon
python scripts/install_startup.py
# The installer can start Riveter immediately.
# Open http://localhost:8766For a foreground development run instead:
python -m pip install -r requirements.txt
python -m src.app 8766Open http://localhost:8766 and work entirely from the Riveter dashboard.
Type a quick reminder into Add a task as you would write it to yourself:
send raj the complete adoption deck in teams
Riveter turns it into a structured task, resolves people, identifies the likely next action, and adds useful context. If a name has multiple matches, choose the right person from the Key people menu before continuing.
- Select a task from the left pane.
- Review its description, priority, due date, people, source, and notes.
- Correct anything that Riveter inferred incorrectly.
- Choose or change the action type, such as Schedule meeting, Reply by email, Follow up, or Prepare.
- Add a note when Cowork needs extra context that is not in the source material.
Select Preview with Cowork to research the task and prepare the action. Cowork can check Microsoft 365 context, draft a response, or find meeting availability. Nothing is sent during preview.
If Cowork needs a decision, answer directly in the task card. Review and edit the final draft or meeting details, confirm the destination, and then use the final approval button to perform the action.
- Mark complete when the work is finished. Delivered Cowork actions also show a subtle completion button in their receipt.
- Use Waiting when someone else owes the next move.
- Use Snooze when the task should return later.
- Accept useful suggestions and dismiss ones that are not actionable.
- Use Refresh when the task context or source conversation has changed.
Riveter runs Microsoft 365 discovery and task maintenance in the background, so normal use does not require terminal commands.
App-wide settings live in data/settings.json, which is gitignored because it
is per-user. Every value fails closed: if the file is missing, unreadable or
malformed, TodoIQ falls back to its shipped defaults rather than to no
behaviour at all.
{
"cowork_api_transport": true,
"cowork_voice": {
"teams": "work-teams-voice",
"email": "work-email-voice",
"default_channel": "teams"
},
"meeting_preferences": {
"default_minutes": 25,
"start_offset_minutes": 5,
"notes": ""
}
}Cowork drafts are written in your own voice using a Cowork skill, chosen by the
channel the task is bound to. Set teams and email to the skill you want for
each. Set either to null to name no skill for that channel; the inline
mechanics (contractions, no em-dashes, no corporate filler, channel-specific
openings and sign-offs) still apply, because a skill lives outside this repo and
can change or fail to resolve without a code change.
default_channel is the voice used when a task carries no channel signal of its
own — typically one you typed yourself rather than one derived from a Teams
thread or a mail item. It is the LAST thing consulted: a task from a Teams
thread is written in the Teams voice regardless of what this is set to. It
selects a voice only, and never binds a recipient, so a task with no destination
still shows "No delivery destination selected". Leave it null to keep the
neutral register, which avoids both a subject line and a sign-off.
Standing defaults applied whenever a draft proposes or books a meeting time.
default_minutes is the length to assume, and start_offset_minutes is how far
past the hour or half hour to start. The offset is fixed and does not scale with
length: at 5, a 25 minute meeting runs :05 to :30 and a 55 minute meeting runs
:05 to :00. notes is free text for anything else standing ("Never book me
before 9am").
Omit the block entirely and nothing is added to the prompt. Values that are not sane numbers are dropped rather than passed through, so a malformed block behaves like an absent one.
This is deliberately not tied to a task's action type. The per-action guidance is, and only 6 of the 17 open tasks that read as scheduling are classified that way, so anything keyed to it applies about a third of the time. These preferences ride every prompt, phrased as a condition, so they also apply when a task is redirected into a meeting after the fact.
See CLAUDE.md for detailed architecture, database schema, and development notes.
Claude Code Commands (/todo-refresh, /todo-add, skills)
|-- calls WorkIQ MCP for M365 data
|-- writes results to SQLite
SQLite DB (data/claudetodo.db)
|-- tasks, task_context, refresh_schedule, sync_log
Tornado Web Server (localhost:8766)
|-- reads SQLite, serves dashboard + REST API + WebSocket
TodoNess can run as a background app with a system tray icon that starts automatically at logon.
# Install dependencies and register startup task
python scripts/install_startup.py
# To remove from startup
python scripts/uninstall_startup.pyThe tray icon provides:
- Double-click to open the dashboard
- Sync Now to trigger a manual M365 scan
- Stop & Exit to shut down
Logs are written to data/todoness.log. Requires pystray and Pillow (installed automatically by the install script).
Run a separate, fictional demo on port 8776. It uses only data/demo/ and
hard-disables WorkIQ, Copilot, Cowork, and Microsoft 365 actions.
# Create/reset the fictional data (server must be stopped)
python scripts/demo_server.py reset
# Start persistently in the background
python scripts/demo_server.py start
# Open http://localhost:8776
# Check or stop it
python scripts/demo_server.py status
python scripts/demo_server.py stopThe demo dataset includes suggested, active, waiting, snoozed, and completed tasks plus ready, delivered, unconfirmed, and safe scheduling-fallback Cowork cards. Reset is deterministic, so recordings can start from the same state.
Core app: tornado, jinja2 (see requirements.txt).
Tray launcher (optional): pystray, Pillow.