Skip to content
Automation
Skill

/morning-briefing

Generate a daily morning briefing: email, calendar, Discord, and news — delivered via voice or Discord DM.

From plugin
sutando
40179 skills18 hooks

Claude Code

$ npx -y skills add sonichi/sutando --skill morning-briefing --agent claude-code

SKILL.md

morning-briefing.SKILL.md
name: morning-briefing
description: "Generate a daily morning briefing: email, calendar, Discord, and news — delivered via voice or Discord DM."
user-invocable: true

Morning Briefing

Generate a prioritized daily briefing from all your channels.

**Usage**: `/morning-briefing`

ARGUMENTS: $ARGUMENTS

What to gather

**Step 0 — Calendar cache. CONDITIONAL: Google-calendar hosts only.**

`src/morning-briefing.py` cannot reach the owner's Google Workspace calendar; it reads a cache the *agent* writes. Omitting this is silent: the briefing reports "no calendar source is configured. Connect Google Calendar via Settings → Integrations, or set MORNING_BRIEFING_CALENDAR_SOURCE=macos to use the local Calendar app". Pull today's local-day events from the Google connector (order: the Station connector; if not connected, the owner's own `mcp__claude_ai_Google_Calendar__*` tools when present; otherwise the one-line note below), then:

echo '[{"raw":"9:00-9:30am 1:1 w/ Sam","calendar":"work"}]' | python3 src/write_calendar_cache.py
python3 src/write_calendar_cache.py --empty   # ONLY for a genuinely empty day

**Hosts with no Google connector skip STEP 0 ONLY.** The reader never touches the local macOS Calendar or Reminders app on its own (they raise a macOS permission prompt); an owner who wants them sets `MORNING_BRIEFING_CALENDAR_SOURCE=macos` once. Step 1 below still runs on every host. See "Calendar source (Google Workspace) — activation" for the full contract.

**A missing connector is one line of text, never a card.** If `composio_find` reports the owner's calendar or mail app `connected: false`, say so in the briefing ("Google Calendar isn't connected; connect it in s.space") and move on. The briefing is not an owner request: never post a connect card or start a `connect-apps` wait from it.

**Step 1 — Base data (canonical; runs on EVERY host, including hosts that skipped Step 0):**

WORKSPACE="$(bash scripts/sutando-config.sh workspace)"
python3 src/morning-briefing.py

`src/morning-briefing.py` is the single source of truth for core briefing data: weather (Open-Meteo), the calendar cache (or macOS Calendar + Reminders, opt-in only), overnight Discord DMs, pending questions, and system health. It writes output to `results/proactive-<ts>.txt` and sends a Discord DM directly. Review its output before composing the full briefing — do NOT re-fetch those sources manually.

**Weather location:** If the base briefing asks which city or town to use, keep that question in the delivered briefing and omit weather until the owner answers. Do not infer a location from timezone or use a default city. When the owner answers, resolve their city to coordinates (clarify ambiguous place names) and save `WEATHER_LAT` and `WEATHER_LON` in the existing `env` stanza of `sutando.config.local.json`, preserving other settings. Subsequent briefings use those saved coordinates.

**Then augment with the following if configured (skip if not available):**

1. **Email** — Read the unread inbox through the Station Gmail connector (`composio_find` / `composio_exec`), or `gws gmail +triage` where the Station isn't available. Summarize top 5 by priority. Flag anything urgent.

2. **GWS Calendar** — If the user uses Google Calendar (not just macOS Calendar), run `gws calendar +agenda --today`. List any meetings not already covered by the macOS Calendar output above.

3. **Friction check** — Run `python3 src/friction-detector.py`. If friction items found, include as "⚠️ Friction: [count] items need attention" with the top 3.

How to deliver

`src/morning-briefing.py` already writes `results/proactive-<ts>.txt` (spoken by voice) and sends a Discord DM for the base data. If you gathered email in steps 1–3, append it as a follow-up proactive file:

echo "📧 Email: [count] unread. [summary]" > "$WORKSPACE/results/proactive-$(date +%s).txt"

Calendar source (Google Workspace) — activation

`src/morning-briefing.py` is a standalone script and **cannot reach the owner's Google Workspace calendar** — the Station/Composio connector is agent-only. So the briefing reads a cache that the *agent* produces:

  • **Producer:** `src/write_calendar_cache.py` writes `state/calendar-today.json` — `{"date": "YYYY-MM-DD", "events": [{"raw": "...", "calendar": "..."}]}`, atomically (tmp + `os.replace`). `date` is today in local time so a stale cache is ignored, and `events: []` means a *verified-empty* day (never rendered as "clear" from a missing cache). Feed it the events you pulled from the connector:
  echo '[{"raw":"9:00-9:30am 1:1 w/ Sam","calendar":"work"}]' | python3 src/write_calendar_cache.py
  python3 src/write_calendar_cache.py --empty   # verified no events today
  • **Reader:** `get_calendar_events()` reads the cache. Set `MORNING_BRIEFING_CALENDAR_SOURCE=google` to make the cache the *only trusted source* — if it's missing/stale the briefing reports "couldn't read your calendar" rather than reading a local macOS Calendar that may not include the work account (the 2026-07-21 "falsely clear" bug, #2256). With no source at all it says "no calendar source is configured. Connect Google Calendar via Settings → Integrations, or set MORNING_BRIEFING_CALENDAR_SOURCE=macos to use the local Calendar app", and while reminders are not read: "Reminders not read: the local Reminders app is opt-in (set MORNING_BRIEFING_CALENDAR_SOURCE=macos to include it)".
  • **Local macOS Calendar + Reminders are opt-in:** `MORNING_BRIEFING_CALENDAR_SOURCE=macos` (set by the owner, never by you), or the owner's host opt-in `python3 skills/macos-tools/scripts/native_pim_consent.py grant`. Reading them raises a macOS Automation prompt, so the default never touches them. One AppleScript read, no app launch, no retry; a denial (`-1743`) is recorded once in `state/calendar-automation-denied` (the shared `native_pim_consent` marker) and never re-asked — the owner grants access in System Settings and r
Read more
@sonichi
Ships withsutando

My AI Stand — Realtime by Day, Rewriting Itself by Night. Summon my AI superpower. Voice, vision, screen, meetings, calls when I'm engaged. Learns my patterns, ships its own code when I'm not. Runs across my Macs, interacts with people & their Stands.

Stars on GitHub

Momentum

stars in total
401
Star history of sonichi/sutando on GitHub, a chart by star-history.com

Other skills on sutando.

ag2space-voice

ag2space-voice

s.space voice surface — binds the room the s.space client announces to the voice session's origin, so work delegated by voice in…

@sonichi@sonichiInstall Skill
agent-activity

agent-activity

Streams what the agent is doing into the room, as rows the desktop client renders in an **events drawer** above the composer…

@sonichi@sonichiInstall Skill
agent-registry

agent-registry

Local Agent Registry — a standalone, dependency-free service that tracks running Claude Code (and other) agent instances. Agents…

@sonichi@sonichiInstall Skill
agent-room-ops

agent-room-ops

For an all-room analysis sweep, use the tested window collector and coverage contract in…

@sonichi@sonichiInstall Skill
answer-format

answer-format

Deterministic final-answer normalizer — a last-step pass for any task that ends in a *precise* answer (a number, a short string,…

@sonichi@sonichiInstall Skill
audio-transcribe

audio-transcribe

Transcribes audio files and voice notes to text via Gemini 2.5-flash. Integrates with Slack, Discord, and Telegram bridges so…

@sonichi@sonichiInstall Skill

More skills from other plugins.

agent-builder

agent-builder

Load immediately after an Agent intent, before the first agent_builder_* call. Governs how you create, configure, test, and…

n8n12d209k
@n8n-io@n8n-ioInstall Skill
browser-use

browser-use

Direct browser control via CDP for web interaction: automation, scraping, testing, screenshots, and site/app work. Also covers…

@browser-use@browser-useInstall Skill
agent-browser

agent-browser

Browser automation CLI for AI agents. Use when the user needs to interact with websites, including navigating pages, filling…

@vercel-labs-2@vercel-labs-2Install Skill
add-anydoc

add-anydoc

Add local office-document-to-Markdown conversion to NanoClaw agent containers with the pinned Firecrawl AnyDoc CLI. Use when…

@nanocoai@nanocoaiInstall Skill

Questions about morning-briefing.

Which coding agents can use morning-briefing?
morning-briefing installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.