---
name: daily-morning-brief
description: "Weekdays at 7:30: today's meetings from Google Calendar, the emails that need a reply from Gmail, and your Linear issues due today or overdue. Use when the user asks for this, or when it runs on a schedule."
---

# Daily morning brief: calendar, inbox and issues

Weekdays at 7:30: today's meetings from Google Calendar, the emails that need a reply from Gmail, and your Linear issues due today or overdue.

The first twenty minutes of a founder's day tend to go to a loop through three apps: what is on the calendar, what is in the inbox, what is due. Each app is good at its own part, and none of them knows about the other two.

This brief does the loop before you sit down. It lists the meetings with who is in them and the free stretch for focused work, the few emails that need an answer, and the issues assigned to you that are due. It only reads: nothing is accepted, sent or moved.

## Two ways to get the data

Use the API or MCP route when you have an MCP server, a CLI or an API token for the app. Otherwise, if you can drive a browser the user is signed in to (Claude in Chrome, a Playwright or Chrome DevTools MCP server), use the browser route. Say which one you used.

## Route A: API or MCP server

### What you need

- Read access to Google Calendar and Gmail (`calendar.readonly`, `gmail.readonly`) through connectors or MCP servers, or one Google OAuth client.
- The Linear MCP server, or a personal Linear API key in `LINEAR_API_KEY`.

If something is missing, say what and stop; do not invent numbers.

### Steps

1. **Read today's calendar** (Google Calendar): Call `events.list` on `primary` with `timeMin` and `timeMax` for today in your timezone, `singleEvents=true` and `orderBy=startTime`. Drop events you declined (`attendees[].self` with `responseStatus: declined`) and all-day blocks, and find the longest free stretch between 9:00 and 18:00.
2. **Pick the emails that need you** (Gmail): Search `is:unread in:inbox newer_than:2d -category:promotions -category:social -category:updates` and keep up to five messages that a person wrote to you, not a list or a notification, each with the ask in one line.
3. **List your issues due** (Linear): Query the Linear GraphQL API with `issues(filter: { assignee: { isMe: { eq: true } }, dueDate: { lte: "2026-10-16" }, state: { type: { nin: ["completed", "canceled"] } } })` and today's date, asking for `identifier`, `title`, `dueDate`, `priority` and `url`.
4. **Write the brief**: Meetings in order with attendees and any doc linked in the description, then the emails, then the issues with overdue ones first, under a one-line summary: first meeting, free time, how many things need you.

## Route B: the browser

### What you need

- Signed in to Google (the calendar and mailbox in question) and to Linear with the right workspace chosen; a second Google account needs its own tab.

If something is missing, say what and stop; do not invent numbers.

### Steps

Start at https://calendar.google.com/. The user is signed in already; never type passwords or codes, and ask if a sign-in page appears.

1. **Read today in Google Calendar**: Switch the view to **Day** (press `D`). Read each event's time, title and guests from its popup, skip events you declined (shown struck through or faded) and the all-day row at the top, and find the longest free stretch between 9:00 and 18:00.
2. **Pick the emails that need you**: Open https://mail.google.com/ and search `is:unread in:inbox newer_than:2d -category:promotions -category:social -category:updates`. Keep up to five messages a person wrote to you, not a list or a notification, and open each to write the ask in one line.
3. **List what is due in Linear**: Open https://linear.app/, pick the workspace, then **My issues > Assigned**. Press `F` to filter: **Due date** before tomorrow and **Status** not Done or Canceled, then set **Display options > Ordering: Due date**. Read identifier, title and due date, overdue first.
4. **Write the brief**: One line on top (first meeting, free stretch, how many emails and issues), then the meetings, the reply list and the issues. Nothing is accepted, sent or moved.

Note: The calendar shows only the calendars ticked in the left sidebar, so tick a shared one first if it should count. Opening emails marks them read, which the API route avoids. Linear's My issues page needs a workspace in the URL, so the agent starts from linear.app and picks it.

## The report

- One line on top: the first meeting, the free stretch, and how many emails and issues need you.
- **Meetings**: time, title, who.
- **Reply today**: sender and subject, with the ask.
- **Due in Linear**: identifier, title, due date, overdue first.

## Post it to Briefkin

When `BRIEFKIN_TOKEN` is set, or `~/.config/briefkin/env` exists (the installer from https://briefkin.dev/docs writes it), also send the result to the user's Briefkin board as one card. Keep the `item_key` the same on every run so the card updates in place, use a new `event_id` per run, and put today's real numbers in place of the example ones. If the request fails, say so once and carry on.

```bash
[ -n "${BRIEFKIN_TOKEN:-}" ] || . ~/.config/briefkin/env
curl -sS -X POST "${BRIEFKIN_URL:-https://briefkin.dev}/v1/events" \
  -H "authorization: Bearer $BRIEFKIN_TOKEN" \
  -H "content-type: application/json" \
  -d @- <<'JSON'
{
  "v": 1,
  "event_id": "daily-morning-brief/<date of this run, e.g. 2026-10-16>",
  "item_key": "daily-morning-brief",
  "project": "Acme",
  "source": "Daily morning brief: calendar, inbox and issues skill",
  "kind": "update",
  "title": "4 meetings, 3 emails to answer, 2 issues due",
  "summary": "First meeting at **9:30**. Free from **13:00 to 15:30** for focused work.",
  "widget": [
    {
      "type": "Text",
      "props": {
        "text": "Meetings",
        "variant": "heading"
      }
    },
    {
      "type": "Table",
      "props": {
        "columns": [
          "Time",
          "Meeting",
          "With"
        ],
        "rows": [
          [
            "9:30",
            "Weekly product sync",
            "Product team (6)"
          ],
          [
            "11:00",
            "Investor call: Q3 update",
            "Dana Whitfield"
          ],
          [
            "12:00",
            "Lunch with candidate",
            "Jordan Lee"
          ],
          [
            "15:30",
            "Renewal call",
            "Fieldstone Realty (2)"
          ]
        ]
      }
    },
    {
      "type": "Text",
      "props": {
        "text": "Reply today",
        "variant": "heading"
      }
    },
    {
      "type": "Table",
      "props": {
        "columns": [
          "From",
          "Subject"
        ],
        "rows": [
          [
            "Luis Ortega",
            "Contract redlines, clause 7"
          ],
          [
            "Ellen Park",
            "September close: 3 receipts"
          ],
          [
            "Hannah Cole",
            "Pilot pricing for 40 seats"
          ]
        ]
      }
    },
    {
      "type": "Text",
      "props": {
        "text": "Due in Linear",
        "variant": "heading"
      }
    },
    {
      "type": "Table",
      "props": {
        "columns": [
          "Issue",
          "Title",
          "Due"
        ],
        "rows": [
          [
            "ENG-398",
            "Draft hiring plan for Q1",
            "Overdue 2 days"
          ],
          [
            "ENG-412",
            "Review pricing page copy",
            "Today"
          ]
        ]
      }
    }
  ]
}
JSON
```

Widgets come from the Briefkin catalog (https://briefkin.dev/v1/catalog). Without a token, just give the user the report.

## Run it on a schedule

Suggested: Weekdays at 7:30 (`30 7 * * 1-5`). From cron, with the agent signed in on that machine:

```bash
30 7 * * 1-5 claude -p "Run the daily-morning-brief skill"
# Codex: codex exec, Gemini CLI: gemini -p, Copilot CLI: copilot -p, OpenCode: opencode run
```

Or use the agent's own scheduler (Claude Code routines, Codex automations, Claude or ChatGPT scheduled tasks): https://briefkin.dev/skills/daily-morning-brief#schedule

Source: https://briefkin.dev/skills/daily-morning-brief
