Start every weekday with one brief from your calendar, Gmail and Linear

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.

Runs
Weekdays at 7:30
Posts
Report card

What lands on your board

AcmeDaily morning brief: calendar, inbox and issues · Claude Code

4 meetings, 3 emails to answer, 2 issues due

First meeting at 9:30. Free from 13:00 to 15:30 for focused work.

Meetings

TimeMeetingWith
9:30Weekly product syncProduct team (6)
11:00Investor call: Q3 updateDana Whitfield
12:00Lunch with candidateJordan Lee
15:30Renewal callFieldstone Realty (2)

Reply today

FromSubject
Luis OrtegaContract redlines, clause 7
Ellen ParkSeptember close: 3 receipts
Hannah ColePilot pricing for 40 seats

Due in Linear

IssueTitleDue
ENG-398Draft hiring plan for Q1Overdue 2 days
ENG-412Review pricing page copyToday
Done
An example with made-up numbers. Your agent posts your real ones.

What it does

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.

How it works

  1. 1Read today's 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. 2Pick the emails that need you

    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. 3List your issues due

    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. 4

    4Write 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.

  5. Post it to the board

    With BRIEFKIN_TOKEN set, the agent sends the result as one card that updates in place every run. Without it, you get the report in the chat.

What you get

  • 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.

Install and run it

Pick your agent, where the data comes from and how to schedule it; the commands below follow.

Agent
Data
Schedule
  1. Install the skill

    One command. It puts the SKILL.md in ~/.claude/skills and in ~/.agents/skills, which Codex, Cursor, Gemini CLI, Copilot CLI and OpenCode read too.

    shellcurl -fsSL https://briefkin.dev/skills/daily-morning-brief/install | sh
  2. Run it

    Ask Claude Code:

    promptRun the daily-morning-brief skill

    Or paste the prompt instead of installing:

    promptMake my morning brief for today. From Google Calendar (primary), list today's events in order with time, title and attendees, leaving out ones I declined and all-day blocks, and tell me the longest free stretch between 9:00 and 18:00. From Gmail, pick up to five unread emails from the last two days that a person wrote to me and that need a reply, with the ask in one line. From Linear, list issues assigned to me that are due today or overdue and not completed or canceled, overdue first. Start with one line: my first meeting, my free time, and how many emails and issues need me. Don't accept, send or change anything.
  3. Put it on a schedule

    Weekdays at 7:30, from cron on any machine where Claude Code is signed in:

    crontab30 7 * * 1-5 claude -p "Run the daily-morning-brief skill"

    Add it with crontab -e. A laptop asleep at that time runs it when it wakes if you use launchd or Task Scheduler instead; GitHub Actions works for the API route.

  4. Send it to your board

    Connect Briefkin once with curl -fsSL https://briefkin.dev/install | sh and every run lands on your board as a report card. How setup works

View the SKILL.mdRaw file
SKILL.md---
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

What your agent needs

  • 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.

Connecting Google Calendar

  1. Claude's Google Calendar connector, added from Claude's connector directory with your Google account, reads your calendars and events.
  2. Google Calendar MCP server, Google's remote server at https://calendarmcp.googleapis.com/mcp/v1, in developer preview alongside Google's other Workspace MCP servers and signed in through an OAuth client you create in Google Cloud.
  3. Calendar API. For your own calendar, an OAuth client with the calendar.events.readonly scope and a stored refresh token in GOOGLE_CALENDAR_REFRESH_TOKEN. For a team or room calendar, share it with a service account's email using "See all event details", point GOOGLE_APPLICATION_CREDENTIALS at the key and set CALENDAR_ID.

calendar.events.readonly is all an agenda or meeting-load report needs, and a calendar shared as "See all event details" gives the service account no way to edit or delete events.

Connecting Gmail

  1. Claude's Gmail connector. In Claude, connect Gmail from the connector directory with your Google account to search and read your mail.
  2. Gmail MCP server, Google's own remote server at https://gmailmcp.googleapis.com/mcp/v1, in developer preview with the other Google Workspace MCP servers. It needs an OAuth client in Google Cloud set up for an AI agent (setup).
  3. Gmail API with OAuth. Create a desktop OAuth client, authorize once with the gmail.readonly scope, and store GMAIL_CLIENT_ID, GMAIL_CLIENT_SECRET and GMAIL_REFRESH_TOKEN. Publish the OAuth app (or make it Internal in Workspace): refresh tokens from an app left in Testing expire after seven days.

gmail.readonly can search and read but not send, delete or relabel; add gmail.compose only if you want the agent to leave drafts.

Connecting Linear

  1. Linear MCP server, Linear's official remote server at https://mcp.linear.app/mcp. Add Linear from Claude's connector directory, or run claude mcp add --transport http linear https://mcp.linear.app/mcp in Claude Code, and sign in with OAuth.
  2. GraphQL API with a personal API key. Create a key in Linear's settings under Security & access, store it in LINEAR_API_KEY, and send it as the Authorization header with no Bearer prefix. For a workspace bot, an OAuth app with the read scope does the same job.

When you create the key, give it Read access and only the teams in the report; it then can't create or edit issues.

Questions

Which calendars does it read?

Your primary calendar by default. To include a shared team calendar or a second account, list them in the prompt; the agent finds their IDs with calendarList.list, merges the events and marks which calendar each came from.

We use Jira, not Linear. Can it still work?

Yes. Swap the third step for a JQL search such as assignee = currentUser() AND duedate <= endOfDay() AND statusCategory != Done through the Jira API or MCP server; the rest of the brief stays the same.

Do I need Briefkin to use the Daily morning brief: calendar, inbox and issues skill?

No. The skill runs with your own agent and gives you the report in the chat. With a Briefkin token set, each run also posts it to your board as a report card, so you can glance at it instead of asking again.

Which agents can run it?

Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot CLI, OpenCode, Windsurf and Amp all read SKILL.md files. The install command puts it in ~/.claude/skills and ~/.agents/skills, where they look. ChatGPT, the Claude app and Grok take the prompt instead. Pick your agent under "Install and run it" and the commands change to match.

Can it work without an API or MCP server, from my browser?

Yes. Switch the data source to "Your browser" and the steps change to the Google Calendar, Gmail and Linear pages themselves: the agent opens calendar.google.com in a browser you are signed in to and reads the numbers off the page. Claude Code, Codex, Cursor, Claude app and ChatGPT can drive a browser out of the box; Gemini CLI, Copilot CLI and OpenCode need a Playwright or Chrome DevTools MCP server first. It is slower than the API and needs you signed in, so it suits a report you run by hand or from a scheduler on your own computer.

Read this report on your board, not in a chat log

Skills are free to use with any agent. Briefkin is where their results land: one board for every report, number and question your agents send, with a ping when something needs you.

Free during the open beta. No card.