Email scanning pipeline — fetches, deduplicates, and classifies emails from all configured Gmail accounts using 3-tier classification, then creates GitHub Issues for actionable items.
npx claudepluginhub queen-of-code/executive-assistant --plugin moms-executive-assistantThis skill uses the workspace's default tool permissions.
Guides execution of the MEA email scan pipeline: Gmail fetch → dedup → 3-tier classify → GitHub Issue creation → state update. Supports multiple mailboxes and full 3-tier classification (Phase 2).
Guides Next.js Cache Components and Partial Prerendering (PPR) with cacheComponents enabled. Implements 'use cache', cacheLife(), cacheTag(), revalidateTag(), static/dynamic optimization, and cache debugging.
Migrates code, prompts, and API calls from Claude Sonnet 4.0/4.5 or Opus 4.1 to Opus 4.5, updating model strings on Anthropic, AWS, GCP, Azure platforms.
Automates semantic versioning and release workflow for Claude Code plugins: bumps versions in package.json, marketplace.json, plugin.json; verifies builds; creates git tags, GitHub releases, changelogs.
Guides execution of the MEA email scan pipeline: Gmail fetch → dedup → 3-tier classify → GitHub Issue creation → state update. Supports multiple mailboxes and full 3-tier classification (Phase 2).
Read task-data/mea-config.json using lib/config.ts loadConfig(). Fail clearly if not found — the user needs to run /configure-mea first.
Determine scan window:
lib/state.ts getLastScanTimestamp(mailboxId)"How far back should I scan for the initial setup? (1–90 days, default 30)" Accept the answer (or default to 30) and use it as N for the first-run query.
after:{lastScanTimestamp} + category/spam filters (see below)--backfill N: query with after:{N days ago} + filters, regardless of timestampGmail filter applied to all scans (connector and MCP mode):
-category:promotions -category:social -category:updates -in:spam -in:trash
Append this to every query. This excludes Gmail's auto-categorised low-value tabs and captures read-but-unactioned emails that is:unread would miss.
Fetch emails — method depends on config.gmailMode:
If gmailMode === "connector" (default, single account):
If gmailMode === "mcp" (multi-account):
gmail_search MCP tool from the bundled MCP servergmail_search({ account: mailbox.email, query: "after:{lastScanTimestamp} -category:promotions -category:social -category:updates -in:spam -in:trash", maxResults: 50 })gmail_search({ account: mailbox.email, query: "after:{N days ago} -category:promotions -category:social -category:updates -in:spam -in:trash", maxResults: 50 })gmail_list_accounts returns an empty list, the MCP server has no tokens — surface a clear error:
"Gmail MCP server has no authenticated accounts. Run: cd mcp/gmail-server && npm run auth -- --account {email}"Both modes:
config.scheduling.emailScan.maxEmailsPerRun (default: 50)messageId, subject, sender, date, snippetDedup (Layer 1):
lib/dedup.ts filterNewEmails(emails)Classify — 3-tier pipeline:
Tier 1 — lib/classify.ts classifyTier1(email, config.classificationRules, config.urgencyRules)
Tier 2 — lib/classify.ts classifyTier2(email, config.urgencyRules, tier2Config)
tier2Config from:
vipSenders: from config.urgencyRules.vipSendersmeetingNoteSenderPatterns: from config.meetingNotes.senderPatternsTier 3 — Haiku LLM (for the remaining ~20%)
lib/classify.ts buildTier3Prompt(email, availableTags)
availableTags: all fully-prefixed tags from the tag registry (lib/tag-engine.ts tagsForDimension() across all dimensions)lib/classify.ts tier3ResponseToResult(response)unclassifiedResult()Fallback — lib/classify.ts unclassifiedResult(mailboxId)
mailbox/{id} and source/email onlyTier tracking:
state.stats.tierBreakdown.tier1 / .tier2 / .tier3 based on which tier classified the emailDedup (Layer 2):
lib/dedup.ts findExistingIssue(email)Create issue — method depends on what GitHub integration is available:
⚠️ Do NOT use
lib/github-adapter.tswhen running inside Cowork with the GitHub connector attached.GitHubAdapterrequiresGITHUB_TOKENand will fail if only the connector is present. Use whichever path applies:
If the GitHub MCP connector is attached (Cowork default):
create_issue, add_labels_to_issue, list_labels_for_repo, create_labellist_labels_for_repo, then create_label for any missingcreate_issue with title, body (snippet + metadata block), and labels arrayIf GITHUB_TOKEN is set (CLI or GitHub Actions):
lib/github-adapter.ts GitHubAdapter(config.github)ensureLabelsExist() then createIssue()Both modes — issue body format:
<!-- email-id: {messageId} --> and <!-- due-date: {extractedDueDate} --> if presentlib/state.ts recordCreatedIssue()Record processed:
lib/dedup.ts recordProcessedEmail(email, result, issueNumber)lib/state.ts updateMailboxScanState(mailboxId, { emailCount, issuesCreated, errors })Scanned 12 emails (personal), 8 emails (work)
Classification: 14 Tier 1 (rules), 3 Tier 2 (structural), 3 Tier 3 (Haiku)
Created 5 issues, skipped 15 duplicates
Errors: none
Process config.mailboxes in order. Each mailbox has its own lastScanTimestamp in mea-state.json. Errors in one mailbox do not prevent scanning others — catch per-mailbox and continue.
Gmail access is read-only regardless of mode. In connector mode, the built-in connector uses gmail.readonly OAuth scope. In MCP mode, the bundled server uses the same gmail.readonly scope. This skill must never attempt to send, archive, modify, or delete emails. Any code path that writes to Gmail is a bug.
Track which tier classified each email. The tierBreakdown stat in mea-state.json surfaces this in /mlea-status. Tier 3 calls cost money; the breakdown lets the user see if their rules need tuning.