meeting-prep
Prepare briefings for today's meetings — attendee research, email history, past meeting notes, LinkedIn, and company context. Use when running the daily meeting prep cron, or when user asks to prepare for meetings, review who they're meeting with, or get context on upcoming calls.
What this skill does
# Daily Meeting Prep
## Config — read before starting
Read `../config/user.json` (resolves to `~/executive-assistant-skills/config/user.json`).
Extract and use throughout:
- `name`, `full_name` — user's name
- `primary_email`, `work_email` — Gmail accounts to check
- `whatsapp` — WhatsApp number for delivery
- `timezone` — IANA timezone (e.g. America/Argentina/Buenos_Aires)
- `slack_username` — Slack DM target
- `workspace` — absolute path to OpenClaw workspace (e.g. ~/.openclaw/workspace)
Do not proceed until you have these values.
## Debug Logging (MANDATORY)
Read `../config/DEBUG_LOGGING.md` for the full convention. Use `python3 {user.workspace}/scripts/skill_log.py meeting-prep <level> "<message>" ['<details>']` at every key step. Log BEFORE and AFTER every external call (gog, mcporter, Granola, web search). On any error, log the full command and stderr before continuing.
## Scope
- Timezone: {user.timezone}
- Calendars: primary of {user.primary_email} AND {user.work_email}
- Today's meetings only
**Timezone note:** Use explicit ART-bounded ISO8601 timestamps for calendar queries, NOT `--date`. Example: `gog calendar list primary --account <email> --from "2026-03-03T00:00:00-03:00" --to "2026-03-04T00:00:00-03:00" --json`. The `--date` flag uses UTC boundaries which misaligns with ART.
- **ALL meetings with attendees** — both external and internal
- Skip personal/solo events with no attendees (e.g. "Personal Trainer", "Golf", all-day reminders)
## Meeting types
### External meetings (attendees outside your email domains)
Full research brief (email context, Granola, LinkedIn, company research) — see below.
### Internal meetings (all attendees from your email domains: hypergrowthpartners.com, growth.li)
Lighter brief — no LinkedIn/company research needed, but still include:
- Attendee list
- Granola context from previous instances of this recurring meeting
- Recent email threads related to the meeting topic/agenda
- Any open action items from last time
- Format: same structure but skip LinkedIn/company sections
### Recurring collaborative meetings (e.g. podcasts, content sessions with external co-hosts)
These are external meetings — give them full briefs. Don't skip recurring meetings just because they're familiar.
## Error handling
- If `gog calendar` fails for one account: continue with the other account, note "⚠️ [account] calendar unavailable" in output.
- If Granola/Grain fails: continue without meeting history, note it per meeting.
- If WhatsApp delivery fails: attempt Slack delivery. If both fail, save to state file and report error.
## For each meeting
### 1. Event basics
Title, local time ({user.timezone}), attendees.
**RSVP status (MANDATORY):** For each attendee, check `responseStatus` from the calendar event:
- `accepted` → no flag needed
- `needsAction` → flag as "⚠️ hasn't responded"
- `declined` → flag as "❌ declined"
- `tentative` → flag as "❓ tentative"
If ANY non-organizer external attendee has NOT accepted (`needsAction`, `tentative`, or `declined`), add a visible line in the brief:
> ⚠️ *RSVP:* <name> hasn't accepted yet
This is informational — it doesn't mean they won't join, but it's useful to know ahead of time, especially for first calls or important meetings.
### 2. Email context (90-day lookback, with historical fallback)
Search Gmail both accounts for exchanges with attendees. For EACH attendee, search using these strategies in order:
1. **Email address** (primary — from calendar invite): `from:<email> OR to:<email>`
2. **Full name**: `"firstname lastname"`
3. **First name + "intro"**: `"intro firstname"` (catches informal intro subjects)
4. **First name + company**: `"firstname companyname"`
The attendee's email from the calendar invite is the most reliable identifier — always start there.
**Intro discovery** (after general email search):
5. Search for intro emails involving the attendee: `subject:intro <email>`, `subject:intro <firstname>`, `subject:introduction <email>`
6. Also check threads where a third party CC'd/introduced the attendee
**Recent email context** (after intro discovery):
7. Pull the most recent email threads with this attendee (by email address) to surface any recent updates, asks, or context leading into today's call
**Historical fallback** (if no results from 90-day search):
8. Run a broader search with NO date filter: `from:<email> OR to:<email>` — this catches long-standing relationships where the last email was months/years ago. If older threads exist, this is NOT a first call — note the relationship history.
- First call vs follow-up? Base this on ALL email history found (including historical), not just 90-day window
- **If first call: MUST include "who introduced + when" (date) if found in email; if not found, explicitly say "No intro trail found in email"**
- If follow-up: extract updates since last call
- **If email contains a concrete commercial trigger** (pricing, deliverables, scope, budget, urgency, timeline, decision-maker request), include it explicitly in the brief
### 3. Granola context
**Search by ATTENDEE, not by meeting title.** The same recurring meeting may have different titles week to week. Always search by the attendee's name or email to find all past meetings with them.
```bash
# Primary: search by attendee name
mcporter call granola.query_granola_meetings query="meetings with [attendee full name]"
# Fallback: search by company if attendee name yields no results
mcporter call granola.query_granola_meetings query="meetings with [company name]"
```
**Cross-check with `list_meetings`:** If the query results seem stale (oldest match is weeks old but you expect more recent), also run `list_meetings` for `last_week` or `this_week` and scan the participant lists for the attendee's email or name. This catches meetings where the title doesn't mention the attendee or company.
- **Recent (< 3 weeks):** Provide a richer summary (not one-liner): decisions made, key tensions, explicit action items, owners, and unresolved questions
- **Older (3+ weeks):** Broader context — relationship history, past decisions, recurring themes
- **No attendee match but company match exists:** Use company-level context and label it clearly as company-level
- **No results / first meeting:** Note that, provide email context instead
- Preserve citation links `[[N]](url)`
- Include a short explicit line: **"Why this meeting now"** based on prior action items or current email trigger
- **Exact name matching**: When attributing Granola results to an attendee, verify BOTH first AND last name match exactly. Different people can share a first name — never assume a match based on first name alone.
- **Auth failure:** If Granola returns an auth error, run `mcporter auth granola --reset` and retry once. If still failing, note "⚠️ Granola unavailable" and continue without it.
- **Empty summary:** If Granola returns a meeting record but with no/empty summary, note "Previous meeting found but no summary available" — don't silently skip it.
### 4. LinkedIn research
- Search: `"[attendee name] [company] LinkedIn"`
- Extract: current role, background, recent posts/activity
### 5. Company research
- Search: `"[company] recent news"`
- Search: `"[company] funding crunchbase"` (if startup/VC relevant)
- Extract: company stage, announcements, what they do
## Research rules
Read `{user.workspace}/style/MEETING_PREP_RULES.md` for additional research steps.
## Output format
Send via WhatsApp ({user.whatsapp}) AND Slack (DM to {user.slack_username}). **One message per meeting, chronological order, is mandatory.**
**Also send to Chief of Staff:** After sending all meeting briefs, upload the markdown brief file (`{user.workspace}/state/meeting-prep-YYYY-MM-DD.md`) to {user.chief_of_staff.name}'s Slack DM. Use the Slack API `files.upload` (or `files.uploadV2`):
```bash
curl -s -F file=@{user.workspace}/state/meeting-prep-YYYY-MM-DD.md \
-F channels={user.chief_of_staff.slack_dm_chanRelated in Productivity
gitea-workflow
IncludedOrchestrate agile development workflows for Gitea repositories using the tea CLI. Use when working with Gitea-hosted repos and asking to 'run the workflow', 'continue working', 'what's next', 'complete the task cycle', 'start my day', 'end the sprint', 'implement the next task', or wanting guided step-by-step development assistance. Keywords: workflow, orchestrate, agile, task cycle, sprint, daily, implement, review, PR, standup, retrospective, gitea, tea.
microsoft-graph-gateway
IncludedRoute Microsoft Graph work in this workspace. Use when users want to read or write Outlook mail, calendar events, contacts, OneDrive or SharePoint files, Teams, Planner, To Do, users, groups, directory data, or arbitrary Microsoft Graph endpoints from VS Code. Prefer WorkIQ for common read scenarios. Use Microsoft Graph for write actions and gap-read scenarios that need exact Graph properties, filters, permissions, or endpoints.
copilotkit
IncludedUse when building with CopilotKit — setup, development, integrations, debugging, upgrading, or contributing. Routes to the appropriate specialized skill based on the task.
wordly-wisdom
IncludedProvides calibrated decision analysis using Charlie Munger-style multiple mental models, inversion, incentive mapping, circle-of-competence checks, misjudgment audits, second-order effects, and forecast updates. Use when the user asks for an oracle take, a hard call, a decision memo, a premortem, an outside view, a red-team, a sanity-check, what am I missing, think this through, or wants a strategy, hire, investment, plan, product, partnership, or major life choice analysed. Avoid for simple factual lookups or time-sensitive legal, medical, or market questions without fresh evidence.
swain-session
IncludedSession management and project status dashboard. Owns the full session lifecycle (start/work/close/resume), focus lane, bookmarks, worktree detection, and tab naming. Also serves as the project status dashboard — shows active epics, progress, actionable next steps, blocked items, tasks, GitHub issues, and recommendations. Worktree creation is deferred to swain-do task dispatch (SPEC-195). Triggers on: 'session', 'status', 'what's next', 'dashboard', 'overview', 'where are we', 'what should I work on', 'show me priorities', 'bookmark', 'focus on', 'session info'.
gandi
IncludedComprehensive Gandi domain registrar integration for domain and DNS management. Register and manage domains, create/update/delete DNS records (A, AAAA, CNAME, MX, TXT, SRV, and more), configure email forwarding and aliases, check SSL certificate status, create DNS snapshots for safe rollback, bulk update zone files, and monitor domain expiration. Supports multi-domain management, zone file import/export, and automated DNS backups. Includes both read-only and destructive operations with safety controls.