morning-brief
Skill479 starsChanged 24 days agoMITView on GitHub
Prepare a daily briefing from configured calendar, email, reminders and goals sources.
25 other projects use a version of this.
Adopted by
Most recently taken up by
- MaguiSella/second-brain-startertheir own version, first seen Nov 8, 2026
- heypastel/pastel-outbound-systemtheir own version, first seen Nov 8, 2026
- amanuelmamo7/Skillstheir own version, first seen Nov 7, 2026
- rami-maalouf/skillstheir own version, first seen Nov 1, 2026
- rgourley/quant-garagetheir own version, first seen Nov 1, 2026
- itgenius-au/skills-librarytheir own version, first seen Oct 30, 2026
Used with
Projects with it also use meeting-prep.
Other files people use alongside this one.
Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
OpenAISkillmeeting-prep
Use when creating Public Equity Investing meeting prep briefs. Do not use for private diligence, IB, FP&A, legal, or scheduling-only tasks.
Also in 3 projects that use this
Other versions25 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 25
- jezweb/vite-flare-starter★ 49same name
- chacosoldier/compabob★ 34same name
- CodeAlive-AI/ceo-ai-os★ 9same name
- MaximeGaudin/second-brain-starter★ 8same name
- rgourley/quant-garage★ 7same name
- TheCraigHewitt/cowork-starter-pack★ 5same name
- megandmartin/agent-skills-repo★ 3same name
- DScardini91/agentic-os★ 2same name
- heypastel/pastel-outbound-system★ 2same name
- rami-maalouf/skills★ 2same name
15 more not listed
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository21 other files it gives its agents.
- aniket-meSkill
- announcement-digestSkill
- checkinSkill
- deep-researchSkill
- dr-synthesizeSkill
- goals-reviewSkill
- post-meetingSkill
- pre-meeting-briefSkill
- proposal-reviseSkill
- proposal-writeSkill
- schedule-querySkill
- setup-project-managementSkill
- tax-guideSkill
- tips-curateSkill
- tips-integrateSkill
- tips-scoutSkill
- todo-addSkill
- todo-queueSkill
- todo-reviewSkill
- triage-inboxSkill
- weekly-reviewSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
33 rules. 0 are common, 18 are distinctive, and 15 are very specific to this project.
0
Common
Most of the 20 edited versions we read keep these.
18
Distinctive
This author's own choices. Worth a look.
15
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 81
Create triage-config.md: if using auto-triage (see /triage-inbox for format).
- Very specific: line 115
If a health check script exists at ~/.claude-assistant/scripts/check-sync.sh, run it before fetching any data:
- Very specific: line 122
If exit code = 0 (all checks pass): Include a single line at the top of the briefing: System health: all checks passed
- Distinctive: line 123
If exit code > 0 (any failures): Include a warning block in the briefing header summarizing failures only (omit passing checks).
- Distinctive: line 135
Read available config files.
- Very specific: line 137
Read ~/.claude-assistant/config/email-policy.md -- extract VIP lists (Tier 1, Tier 2), family addresses, @ToSelf label ID
- Very specific: line 138
Read ~/.claude-assistant/config/calendar-policy.md -- extract calendar IDs, working hours, city name, timezone
- Very specific: line 139
Read ~/.claude-assistant/config/triage-config.md -- extract label IDs, vendor domains, classification rules (needed only if triage is …
- Very specific: line 140
Read ~/.claude-assistant/config/goals.yaml -- extract objectives, push_level, active priorities
- Distinctive: line 142
If a config file is missing, note it internally and continue.
- Distinctive: line 190
If osascript fails (non-macOS or Reminders not available), skip this phase silently.
- Distinctive: line 194
Run these Gmail searches via MCP (all in parallel):
- Distinctive: line 211
Use the label ID from email-policy.md.
- Very specific: line 222
If /triage-inbox skill is available and triage-config.md exists, run inline triage:
- Distinctive: line 224
Search for unread inbox emails within the adaptive triage window
- Very specific: line 229
Adaptive window: Read last_run from triage-run-state.json.
- Distinctive: line 231
If triage-config.md is missing or triage-inbox skill is not installed, skip this phase and report: "Triage skipped -- install /triage-inbox …
- Distinctive: line 246
If an event has no attendees (e.g., "Focus time"), skip context lookup.
- Distinctive: line 256
If no non-you messages found newer than your sent message, it is a "waiting for"
- Distinctive: line 260
If this adds too much latency, it can be skipped -- the briefing should not block on this.
- Distinctive: line 264
Use WebSearch to query "[Your City] weather today" (city from calendar-policy.md) and extract a one-line summary including temperature, …
- Distinctive: line 268
If WebSearch fails or no city configured, omit the weather line.
- Distinctive: line 322
If no context found, omit the line.
- Very specific: line 335
If goals.yaml was loaded:
- Very specific: line 339
If push_level >= moderate AND >2 hours free: add a research nudge
- Very specific: line 340
If push_level = assertive AND <2 hours free: add a deep work alert
- Very specific: line 449
If you have a send-email script configured at ~/.claude-assistant/scripts/send-email.py:
- Distinctive: line 469
When generating the email version, convert the briefing to HTML using this template structure.
- Distinctive: line 594
No images, no background colors, no external resources -- pure inline HTML
- Very specific: line 604
All search/label tools require user_google_email: your-email@gmail.com
- Distinctive: line 613
Granola MCP unavailable: Use Gmail-only context for meetings.
- Very specific: line 616
Sibling tool call failures: If one MCP call in a parallel batch fails, siblings may also fail.
- Distinctive: line 642
After completing all phases, log this run:
“Common” is measured: kept by at least 6 in 10 of the 20 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Morning Briefing
v1.5 — Unified hard deadline keywords; edge case fixes; structural cleanup
Generate a comprehensive daily morning briefing combining calendar, reminders, inbox state, weather, meeting context, and optional email triage into a single view.
Prerequisites
This skill requires several MCP integrations and config files to function fully. Missing components degrade gracefully (sections are omitted, not errors).
Required:
- Gmail MCP -- for inbox scanning, VIP detection, waiting-for detection
- Google Calendar MCP -- for today's schedule and lookahead
Recommended:
- Config files (see First-Time Setup below):
~/.claude-assistant/config/email-policy.md-- VIP lists, email routing rules~/.claude-assistant/config/calendar-policy.md-- calendar IDs, working hours, city name~/.claude-assistant/config/triage-config.md-- label IDs, vendor domains, classification rules~/.claude-assistant/config/goals.yaml-- objectives and priorities for goal alignment
Optional:
- Granola MCP -- for meeting context from past transcripts
- Apple Reminders (macOS only) -- for task/reminder integration
/triage-inboxskill -- for auto-triage phase- Health check script at
~/.claude-assistant/scripts/check-sync.sh-- for system health monitoring
First-Time Setup
- Create config directory:
mkdir -p ~/.claude-assistant/config mkdir -p ~/.claude-assistant/state mkdir -p ~/.claude-assistant/logs mkdir -p ~/.claude-assistant/scripts - Create calendar-policy.md with at minimum:
## Calendars - primary (your-email@gmail.com) - [add other calendar IDs you want included] ## Working Hours - 8:00 AM to 6:00 PM ## Location - City: [Your City] - Timezone: [YOUR_TIMEZONE] - Create email-policy.md with at minimum:
## VIP List ### Tier 1 (respond within 24h) - [name] <email@example.com> ### Tier 2 (respond within 48h) - [name] <email@example.com> ## @ToSelf Label - Label name: @ToSelf - Label ID: <YOUR_LABEL_ID> - Create goals.yaml (optional but recommended):
push_level: moderate # gentle | moderate | assertive objectives: - name: "Example project" weight: high status: active next_step: "Draft section 3" - Create triage-config.md if using auto-triage (see
/triage-inboxfor format).
Customization Points
| Setting | Where to Configure | Default |
| Weather city | calendar-policy.md > Location > City | Omitted if not set |
| Working hours | calendar-policy.md > Working Hours | 8am-6pm (10 hours) |
| Timezone | calendar-policy.md > Timezone | System timezone |
| Calendar IDs | calendar-policy.md > Calendars | Primary only |
| VIP list | email-policy.md > VIP List | No VIP highlighting |
| Goal alignment | goals.yaml > objectives | Section omitted |
| Deep work push level | goals.yaml > push_level | moderate |
| Email delivery | See Phase 7 below | Terminal only |
| Auto-triage | Requires /triage-inbox + triage-config.md | Skipped |
| Granola meeting context | Requires Granola MCP | Gmail-only context |
| Reminders | Requires macOS (osascript) | Section omitted |
| Health check | ~/.claude-assistant/scripts/check-sync.sh | Skipped if not found |
Arguments
$ARGUMENTS can include:
- (none) -- full briefing, terminal output only
email-- also email the briefing (requires email delivery setup)tomorrow-- show tomorrow's schedule/reminders instead of todayno-triage-- skip the auto-triage phaseno-reminders-- skip the reminders phase (useful on non-macOS)
Multiple arguments can be combined: email tomorrow, no-triage no-reminders, etc.
Instructions
Phase 0: Quick Health Check (< 5 seconds)
If a health check script exists at ~/.claude-assistant/scripts/check-sync.sh, run it before fetching any data:
bash ~/.claude-assistant/scripts/check-sync.sh 2>&1Interpretation:
- If exit code = 0 (all checks pass): Include a single line at the top of the briefing:
System health: all checks passed - If exit code > 0 (any failures): Include a warning block in the briefing header summarizing failures only (omit passing checks). Format:
!! System health: [N] issue(s)
- [failure description 1]
- [failure description 2]Never block the briefing on health check results -- failures are informational only. If the script is not found or fails to run, skip this phase silently and continue to Phase 1.
Phase 1: Read Config Files
Read available config files. Missing files are not errors -- skip the corresponding sections.
- Read
~/.claude-assistant/config/email-policy.md-- extract VIP lists (Tier 1, Tier 2), family addresses, @ToSelf label ID - Read
~/.claude-assistant/config/calendar-policy.md-- extract calendar IDs, working hours, city name, timezone - Read
~/.claude-assistant/config/triage-config.md-- extract label IDs, vendor domains, classification rules (needed only if triage is enabled) - Read
~/.claude-assistant/config/goals.yaml-- extract objectives, push_level, active priorities
If a config file is missing, note it internally and continue. The briefing adapts to available data.
Phase 2: Calendar Data
Query all configured calendars for today's events (or tomorrow's if tomorrow argument).
For each calendar ID in calendar-policy.md:
mcp__google_workspace__get_events
calendar_id: [calendar ID]
time_min: [target date]T00:00:00[YOUR_TIMEZONE]
time_max: [target date]T23:59:59[YOUR_TIMEZONE]Also fetch lookahead events (tomorrow, or weekend on Fridays):
- On Fridays: fetch Saturday AND Sunday events for "Weekend Preview"
- Other days: fetch next day's events for "Tomorrow Preview"
Processing:
- Deduplicate events appearing in multiple calendars (match by start time + title)
- Filter out declined events
- Sort by start time (all-day events first)
- Tag each event with its calendar name
Phase 3: Reminders (macOS only, skip if no-reminders)
Fetch incomplete reminders from Apple Reminders using osascript:
osascript -e '
tell application "Reminders"
set output to ""
repeat with aList in lists
set listName to name of aList
repeat with aReminder in (reminders of aList whose completed is false)
set rName to name of aReminder
set rDue to ""
try
set rDue to due date of aReminder as string
end try
set rPri to priority of aReminder
set output to output & listName & "|" & rName & "|" & rDue & "|" & rPri & "\n"
end repeat
end repeat
return output
end tell'If osascript fails (non-macOS or Reminders not available), skip this phase silently.
Phase 4: Inbox Scan
Run these Gmail searches via MCP (all in parallel):
4a. VIP unread:
query: "in:inbox is:unread (from:vip1@example.com OR from:vip2@example.com OR ...)"Build the from-list from all Tier 1 and Tier 2 VIP addresses in email-policy.md. If no VIP list configured, skip this search.
4b. Inbox count:
query: "in:inbox is:unread"4c. @ToSelf count:
query: "label:<YOUR_LABEL_ID> is:unread"Use the label ID from email-policy.md. Skip if not configured.
4d. Sent recent (for waiting-for detection):
query: "from:me in:sent newer_than:7d -in:chat"For VIP results (4a), fetch message content to get sender names, subject lines, and dates. Sort oldest-first and calculate days waiting.
Phase 5: Auto-Triage (skip if no-triage argument)
If /triage-inbox skill is available and triage-config.md exists, run inline triage:
- Search for unread inbox emails within the adaptive triage window
- Classify using the logic from
/triage-inbox(VIP safety check, expense detection, classification scoring) - Apply labels via Gmail MCP
- Update
~/.claude-assistant/state/triage-run-state.json
Adaptive window: Read last_run from triage-run-state.json. If < 12 hours ago, use hours_since_last + 2 hours. If >= 12 hours, use 48 hours. Default: 2 days.
If triage-config.md is missing or triage-inbox skill is not installed, skip this phase and report: "Triage skipped -- install /triage-inbox for auto-triage."
Phase 5a: Meeting Context (next 2 events)
Using calendar data from Phase 2:
- Sort today's timed events by start time
- Identify the next 2 upcoming events (start time >= now; if run before any meetings, use first 2)
- For each event, extract attendee emails (exclude your own addresses and room/resource addresses)
- For each event, search in parallel:
- Gmail:
(from:{attendee} OR to:{attendee}) newer_than:14dfor the primary attendee - Granola (if available):
mcp__granola__search_meetingswith attendee name
- Gmail:
- Extract: last topic discussed, action items owed, pending decisions
- Compose a 1-line context summary per event
If an event has no attendees (e.g., "Focus time"), skip context lookup. If searches return nothing, show the event without context. Cap at 2 events, 1-2 searches per event.
Phase 5b: Waiting-For Detection
From the sent-email results (Phase 4d):
- Fetch content for the 10 most recent sent messages
- For each, check the thread for replies:
- Skip: self-sends, automated/noreply addresses, bulk sends (5+ recipients)
- Search:
in:anywhere thread:{thread_id} -from:me newer_than:7d - If no non-you messages found newer than your sent message, it is a "waiting for"
- Cap at 5 waiting-for items
- Sort by age (oldest waiting first)
If this adds too much latency, it can be skipped -- the briefing should not block on this.
Phase 5c: Weather
Use WebSearch to query "[Your City] weather today" (city from calendar-policy.md) and extract a one-line summary including temperature, conditions, and precipitation chance.
Example: "Portland: 54F, partly cloudy, 20% chance rain"
If WebSearch fails or no city configured, omit the weather line.
Phase 5d: Tomorrow/Weekend Preview
Using lookahead calendar data from Phase 2 and reminders from Phase 3:
- Normal days: Show tomorrow's all-day events, timed events, and reminders due tomorrow
- Fridays: Replace with "Weekend Preview" showing Saturday AND Sunday events/reminders grouped by day
Phase 6: Assemble & Display Briefing
Reminder Classification Logic
Classify each reminder from Phase 3 into groups:
HARD DEADLINES -- Has hard-deadline keywords AND due within 3 days (including today). Also: any item with priority=1 (manually set high).
Hard-deadline keywords: due, deadline, submit, file, renew, pay, invoice, reimburse, grant, IRB, contract, review, letter, slides, deck, send, deliver, final, revision
Match case-insensitive against reminder title and body.
DUE TODAY -- Due date = target date, not classified as hard deadline.
OVERDUE -- Due date before target date. Sort oldest first (most days overdue at top).
Number all items sequentially across groups (1, 2, 3...) so you can reference them by number in follow-up.
Free Time Calculation
- Working window: from calendar-policy.md (default 8:00 AM to 6:00 PM = 10 hours)
- Sum meeting durations from today's timed events
- Free hours = working hours - total meeting hours
- Display as: [N] hours free (of [M] available, [start]-[end])
VIP Sorting
Sort VIP emails oldest-first (most days waiting at top). Display age as "[N]d" next to each name.
Overdue Truncation
Show a maximum of 10 overdue items (oldest first). If more than 10:
... and [N] more -- run /todo-review to review
Meeting Context Lines
For each of the next 2 events (from Phase 5a), add an indented context line below the event:
-> [context summary]
Good context lines surface actionable info:
- "You owe [Name] draft slides from Jan 30 meeting"
- "Last discussed IRB amendment timeline -- decision pending"
- "New contact -- no prior email or meeting history"
- "Follow-up from Feb 10: agreed to share dataset"
If no context found, omit the line.
Waiting-For Assembly
Each item shows:
- Recipient name (extracted from To: header)
- Subject line snippet (first ~50 chars)
- Days waiting
Sort oldest-waiting first. Cap at 5 items.
Goal Alignment
If goals.yaml was loaded:
- Compare today's calendar events against active objectives
- Count goal-aligned vs admin/service meetings
- Identify top research priority from highest-weight at-risk objective
- If
push_level >= moderateAND >2 hours free: add a research nudge - If
push_level = assertiveAND <2 hours free: add a deep work alert - Keep to 3-5 lines
Briefing Template
Compose the briefing in this format. Omit sections with no data. Use tomorrow's date if tomorrow argument was provided.
# Morning Briefing -- [Day of Week], [Month] [Date], [Year]
[System health line or warning block from Phase 0, if available]
[Weather one-liner, e.g., "[Your City]: 54F, partly cloudy, 20% chance rain"]
## Suggested Priorities
[Generate 3-5 suggested priorities based on:]
1. Hard deadline items (highest urgency)
2. VIP emails awaiting response (by age, oldest first)
3. Today's meetings that need prep
4. Overdue items worth acting on today
5. Goal-aligned work (from goals.yaml)
[Number them in suggested order of importance]
## Goal Alignment
- Today: [N] meetings ([M] align with goals, [K] are admin/service)
- [event name] -> [objective name] (if aligned)
- [N] hours unscheduled -- top research priority: [specific next step from goals.yaml]
[If push_level >= moderate AND >2 hours free:]
Research nudge: [specific actionable next step on top-priority task]
[If push_level = assertive AND <2 hours free:]
!! Deep work alert: Less than 2 hours unscheduled today. Consider declining [lowest-priority meeting].
## Today's Schedule
- [time range] [event name] ([calendar name])
-> [1-line context from Phase 5a, if available]
- [time range] [event name] ([calendar name])
- ...
[If no events: "No events scheduled today"]
**[N] hours free** (of [M] available, [start]-[end])
## Hard Deadlines
1. [[list]] [task name] (due [relative date]) !!
...
[If none: omit entire section]
## Inbox Highlights
- **VIP needing response:** [name] ([N]d), [name] ([N]d) -- sorted oldest-first
- [N] unread emails remain in inbox
- [N] emails in @ToSelf (pending todo conversion)
[If @ToSelf has items: "Run /todo-queue to process"]
## Waiting For
- [Recipient name]: "[subject snippet]" ([N]d ago)
- ...
[Max 5 items, oldest first. If none: omit section]
## Tasks Due Today
N. [[list]] [task name] ([time if set])
...
[If none: omit section]
## Tomorrow Preview
- [All-day events]
- [time range] [event name]
- [[list]] [reminder due tomorrow]
[If nothing tomorrow: "Nothing scheduled for tomorrow"]
[ON FRIDAYS: Replace with "Weekend Preview" showing Sat + Sun grouped by day]
## Triage Summary
Auto-triaged [N] emails: [N] archived, [N] labeled, [N] flagged for review.
APPLIED:
- [Sender (address)] | [Subject snippet, ~50 chars] -> [Label] [reason]
- ...
SKIPPED (left in inbox):
- [Sender (address)] | [Subject snippet] | [Reason: "VIP", "uncertain", etc.]
- ...
[If any flagged:]
!! Flagged: [sender] -> [label] (new sender -- suggest filter)
[If no-triage: "Triage skipped -- run /triage-inbox manually"]
## Overdue ([N] items)
N. [[list]] [task name] (N days overdue)
... [max 10 items, oldest first]
[If >10: "... and [N] more -- run /todo-review to review"]
[If none: omit section]
To adjust reminders: tell me "defer 8-12 to Monday" or "move 9 to Someday"Display in terminal -- this is the default output.
Phase 7: Email Delivery (only if email argument provided)
Email delivery is opt-in. There are two approaches:
Option A: Gmail MCP Draft (simple)
mcp__google_workspace__draft_gmail_message
user_google_email: your-email@gmail.com
to: your-email@gmail.com
subject: "Morning Briefing -- [Day], [Month] [Date], [Year]"
body: [HTML version of briefing]
is_html: trueThis creates a draft you can review and send from Gmail.
Option B: Custom send script (advanced)
If you have a send-email script configured at ~/.claude-assistant/scripts/send-email.py:
# Write HTML to temp file
cat > /tmp/morning-briefing.html << 'BRIEFING_EOF'
[HTML content]
BRIEFING_EOF
# Send
python3 ~/.claude-assistant/scripts/send-email.py \
--to your-email@gmail.com \
--subject "Morning Briefing -- [Day], [Month] [Date], [Year]" \
--body-file /tmp/morning-briefing.html \
--htmlSee the project wiki for send-email.py setup instructions.
HTML Email Template
When generating the email version, convert the briefing to HTML using this template structure. Keep it simple -- inline styles only (no external CSS), compatible with all email clients.
<html>
<body style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; color: #1a1a1a; max-width: 640px; margin: 0 auto; padding: 16px; font-size: 15px; line-height: 1.5;">
<h1 style="font-size: 22px; font-weight: 700; border-bottom: 2px solid #1a1a1a; padding-bottom: 6px; margin-bottom: 4px;">
Morning Briefing -- [Day], [Month] [Date], [Year]
</h1>
<p style="color: #666; margin: 0 0 16px 0; font-size: 14px;">
[Your City]: 54F, partly cloudy, 20% chance rain
</p>
<!-- Suggested Priorities -->
<h2 style="font-size: 17px; font-weight: 700; color: #333; margin: 20px 0 8px 0;">
Suggested Priorities
</h2>
<ol style="margin: 0 0 12px 0; padding-left: 20px;">
<li>...</li>
</ol>
<!-- Goal Alignment -->
<h2 style="font-size: 17px; font-weight: 700; color: #333; margin: 20px 0 8px 0;">
Goal Alignment
</h2>
<ul style="margin: 0 0 12px 0; padding-left: 20px;">
<li>Today: [N] meetings ([M] goal-aligned, [K] admin)</li>
<li>[N] hours unscheduled -- top research priority: <b>[specific next step]</b></li>
</ul>
<!-- Today's Schedule -->
<h2 style="font-size: 17px; font-weight: 700; color: #333; margin: 20px 0 8px 0;">
Today's Schedule
</h2>
<ul style="margin: 0 0 4px 0; padding-left: 20px; list-style: none;">
<li><b>9:00-10:00</b> Event Name <span style="color: #666;">(Calendar)</span>
<br><span style="color: #555; font-size: 13px; padding-left: 12px;">→ Context line</span>
</li>
</ul>
<p style="font-weight: 700; margin: 4px 0 12px 0;">
[N] hours free <span style="font-weight: 400; color: #666;">(of [M] available)</span>
</p>
<!-- Hard Deadlines (red) -->
<h2 style="font-size: 17px; font-weight: 700; color: #c0392b; margin: 20px 0 8px 0;">
Hard Deadlines
</h2>
<ol style="margin: 0 0 12px 0; padding-left: 20px;">
<li><b style="color: #c0392b;">[list] Task name</b> (due [date]) !!</li>
</ol>
<!-- Inbox Highlights -->
<h2 style="font-size: 17px; font-weight: 700; color: #333; margin: 20px 0 8px 0;">
Inbox Highlights
</h2>
<ul style="margin: 0 0 12px 0; padding-left: 20px;">
<li><b>VIP needing response:</b> Name (Nd), Name (Nd)</li>
<li><b>[N]</b> unread emails remain in inbox</li>
<li><b>[N]</b> emails in @ToSelf <span style="color: #666;">(run /todo-queue to process)</span></li>
</ul>
<!-- Waiting For -->
<h2 style="font-size: 17px; font-weight: 700; color: #333; margin: 20px 0 8px 0;">
Waiting For
</h2>
<ul style="margin: 0 0 12px 0; padding-left: 20px;">
<li><b>Recipient Name</b>: "Subject snippet" <span style="color: #666;">(Nd ago)</span></li>
</ul>
<!-- Tasks Due Today -->
<h2 style="font-size: 17px; font-weight: 700; color: #333; margin: 20px 0 8px 0;">
Tasks Due Today
</h2>
<ol start="N" style="margin: 0 0 12px 0; padding-left: 20px;">
<li>[list] Task name</li>
</ol>
<!-- Tomorrow/Weekend Preview -->
<h2 style="font-size: 17px; font-weight: 700; color: #333; margin: 20px 0 8px 0;">
Tomorrow Preview
</h2>
<ul style="margin: 0 0 12px 0; padding-left: 20px;">
<li>...</li>
</ul>
<!-- Triage Summary -->
<h2 style="font-size: 17px; font-weight: 700; color: #333; margin: 20px 0 8px 0;">
Triage Summary
</h2>
<p style="margin: 0 0 6px 0;">
Auto-triaged [N] emails: [N] archived, [N] labeled, [N] flagged for review.
</p>
<p style="font-weight: 600; margin: 8px 0 2px 0; font-size: 14px;">Applied:</p>
<ul style="margin: 0 0 6px 0; padding-left: 20px; font-size: 13px; color: #444;">
<li>[sender@domain] | "Subject snippet" → [Label] <span style="color: #888;">(reason)</span></li>
</ul>
<p style="font-weight: 600; margin: 8px 0 2px 0; font-size: 14px;">Skipped (left in inbox):</p>
<ul style="margin: 0 0 6px 0; padding-left: 20px; font-size: 13px; color: #444;">
<li>[sender@domain] | "Subject snippet" | <span style="color: #888;">reason</span></li>
</ul>
<!-- Overdue -->
<h2 style="font-size: 17px; font-weight: 700; color: #666; margin: 20px 0 8px 0;">
Overdue ([N] items)
</h2>
<ol start="N" style="margin: 0 0 8px 0; padding-left: 20px;">
<li style="color: #666;">[list] Task name (N days overdue)</li>
</ol>
<p style="color: #888; font-size: 13px; margin-top: 0;">
To adjust: tell me "defer 8-12 to Monday" or "move 9 to Someday"
</p>
</body>
</html>Formatting rules:
- Section headers (
<h2>): bold, 17px - Main title (
<h1>): bold, 22px, bottom border - Hard deadlines: red text (
#c0392b) + bold - Overdue items: gray text (
#666) - Calendar names and metadata: gray (
#666) - Schedule times: bold
- VIP names and counts: bold
- Helper text: smaller gray text
- No images, no background colors, no external resources -- pure inline HTML
- Omit sections with no data (same as terminal version)
MCP Parameter Notes
These validated behaviors help avoid common issues:
search_gmail_messages: Does NOT acceptmax_resultsparameterbatch_modify_gmail_message_labels: Useadd_label_ids/remove_label_ids(NOTadd_label_names/remove_label_names). Pass JSON arrays (["id1","id2"]). Works reliably when called sequentially -- failures are caused by parallel sibling-call cascades, not parameter issues.get_gmail_messages_content_batch: May reject list parameters -- fall back to individualmcp__google_workspace__get_gmail_message_contentcalls- All search/label tools require
user_google_email: your-email@gmail.com
Error Handling
- Gmail MCP unavailable: Skip inbox/triage sections. Report "Gmail unavailable." Continue with calendar/reminders.
- Calendar MCP unavailable: Skip schedule. Report "Calendar unavailable." Continue with other sections.
- Calendar 404 for a specific ID: Skip that calendar silently. Others may still work.
- osascript fails: Skip reminders silently (non-macOS or Reminders not running).
- WebSearch fails: Omit weather line.
- Granola MCP unavailable: Use Gmail-only context for meetings.
- Config file missing: Skip dependent sections, note in internal log.
- Batch label apply fails: Retry once standalone, then fall back to individual per-message calls. Report which emails failed.
- Sibling tool call failures: If one MCP call in a parallel batch fails, siblings may also fail. Never fire multiple
batch_modify_gmail_message_labelscalls in parallel -- run them sequentially. Retry failed calls in a separate standalone invocation. - Email delivery fails: Report error. Briefing still displayed in terminal.
- Permission prompt appears: A tool is missing from settings.json allow list. Add it under
permissions.allow.
Examples
/morning-brief # Full briefing, terminal only
/morning-brief email # Full briefing + email delivery
/morning-brief tomorrow # Tomorrow's view
/morning-brief no-triage # Skip auto-triage
/morning-brief no-triage no-reminders # Minimal: calendar + inbox only
/morning-brief email tomorrow # Tomorrow's view + email deliveryIntegration Notes
- Triage rules by reference: This skill uses
/triage-inboxclassification logic andtriage-config.mdfor data tables. Updates to those files propagate automatically -- no rules are duplicated here. - Auto-apply is pre-approved: Unlike
/triage-inboxwhich requiresapplyargument, the morning briefing auto-applies all labels during triage. Both skills read and write the same triage state file, so whichever runs first sets the baseline for the next run. - Shared triage window: Morning brief and
/triage-inboxread the sametriage-run-state.json. Morning brief uses a 2-day floor (vs 1 day for triage-inbox). - VIP detection: Uses the VIP list from
email-policy.mdto highlight unanswered emails from important senders. - @ToSelf integration: Checks for pending todo-queue items and reminds to run
/todo-queue. - Goal alignment: Reads
goals.yamlfor priorities. Keep this file updated for relevant suggestions.
Performance Logging
After completing all phases, log this run:
echo "$(date +%Y-%m-%d),morning-brief,TOOL_CALLS,NOTES" >> ~/.claude-assistant/logs/skill-performance.csvReplace TOOL_CALLS with approximate count of tool uses this run. Replace NOTES with brief volume info (e.g., "12 emails 4 cals"). Do not skip this step.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

