Check Todoist for tasks due today (and overdue) that involve pinging, emailing, or following up with someone. Auto-draft the emails using meeting context and notify via WhatsApp. Use when running the daily due-drafts cron, or when user asks to process email tasks from Todoist.
From executive-assistant-skillsnpx claudepluginhub nickloveinvesting/nick-love-plugins --plugin executive-assistant-skillsThis skill uses the workspace's default tool permissions.
Designs and optimizes AI agent action spaces, tool definitions, observation formats, error recovery, and context for higher task completion rates.
Enables AI agents to execute x402 payments with per-task budgets, spending controls, and non-custodial wallets via MCP tools. Use when agents pay for APIs, services, or other agents.
Compares coding agents like Claude Code and Aider on custom YAML-defined codebase tasks using git worktrees, measuring pass rate, cost, time, and consistency.
Read ../config/user.json (resolves to ~/executive-assistant-skills/config/user.json).
Extract and use throughout:
primary_email, work_email — Gmail accountswhatsapp — for notification deliveryworkspace — absolute path to OpenClaw workspacesignature — email signatureRead ../config/DEBUG_LOGGING.md for the full convention. Use python3 {user.workspace}/scripts/skill_log.py todoist-due-drafts <level> "<message>" ['<details>'] at every key step. Log BEFORE and AFTER every external call (todoist-cli, gog, mcporter). On any error, log the full command and stderr before continuing.
source {user.workspace}/.env
todoist-cli today --json
Also check overdue tasks:
todoist-cli list --filter "overdue" --json
Filter for tasks whose content matches outreach intent:
ping, email, follow up, follow-up, send, reach out, text, message, intro, connect, check in, nudge, reply, respond, draftSkip tasks that are clearly NOT outreach (e.g. "review doc", "read report", "build proposal").
Read and follow ~/executive-assistant-skills/email-drafting/SKILL.md for all drafting rules.
For each task:
# Find the meeting in Granola
mcporter call granola list_meetings --args '{"time_range": "custom", "custom_start": "<meeting-date>", "custom_end": "<meeting-date+1>"}'
# Query for what was discussed with this person
mcporter call granola query_granola_meetings --args '{"query": "What did {user.name} discuss with <recipient> and what did he promise or commit to do?", "document_ids": ["<meeting_id>"]}'
Then cross-check with Grain for the full transcript:
mcporter call grain.list_attended_meetings --args '{}'
# Note: Grain's schema does not support `start_date`/`end_date` filters. Call with empty args and filter the results manually by `start_datetime` to match the meeting date range.
mcporter call grain.fetch_meeting_transcript --args '{"meeting_id": "<grain_meeting_id>"}'
When meeting context is available, the email draft must reflect what was actually said — not just the task title. Look for: specific commitments, timelines discussed, names/projects mentioned, tone of the conversation, and any docs/links promised.{user.work_email} for professional/business contacts or {user.primary_email} for personal contacts. When ambiguous, use {user.work_email}.--thread-id to keep it in the same thread.{user.signature}Send a single WhatsApp message to {user.whatsapp} with:
📬 *Due-today drafts*
<N> email drafts created from today's Todoist tasks:
1. **<recipient>** — <one-line intent> (draft in <account>)
2. ...
Review and send when ready.
If tasks exist but none are outreach-type, report:
📋 *Due-today tasks (no drafts needed)*
<list of today's tasks — quick reference>
If no tasks due today → NO_REPLY (skip notification entirely).
python3 {user.workspace}/scripts/cron_canary.py ping todoist-due-drafts
todoist-cli fails: notify via WhatsApp "⚠️ Todoist due-drafts failed: <error>", ping canary, exit..env file or token expired: report "⚠️ Todoist token unavailable — check agent-secrets lease" and exit.gog --account <account> --no-input gmail search "to:<recipient> in:sent newer_than:14d" --json. If recent sent mail exists in the same thread, skip drafting and note "already replied" in the notification.gog --account <account> --no-input gmail drafts --json. If a draft already exists for the same thread (matching thread ID or recipient + subject), skip and note "draft already exists."