Setting Up a Personal Morning Brief in Claude Cowork
This guide is for Claude Cowork — Anthropic’s AI workspace that can read your email, calendar, and the web, then act on what it finds. If you don’t have it yet, start there.
⏱️ Do this all in one session. The steps build on each other and Claude needs context from earlier prompts. Start a fresh conversation and work through all steps without closing the tab.
What You’re Building
A daily scheduled task that delivers a morning briefing. It runs every day, but not every section runs every day:
- Calendar — Today + next 2-3 days (daily)
- Email — Last 24 hours, filtered into actionable vs noise (daily)
- Career Search — Open roles across AI/cloud companies via public ATS APIs, scored against your resume and preferences (Mon & Thu only)
- LinkedIn Search — Live LinkedIn jobs fetched and scored against your preferences (Mon & Thu only)
Sections 3 and 4 are optional — only set them up if you’re actively job hunting.
Choose your path
- Just calendar + email? Do Steps 0–2, then jump to Step 4 (Test) and Step 5 (Schedule). Skip Step 3 entirely.
- Calendar + email + career search? Do every step in order.
You can add (or remove) career search later — see the Maintenance section at the bottom.
Before You Start: Set Up Gmail and Calendar Access
Do this first, in any conversation — it only needs to happen once. Paste this into Claude:
I need you to be able to read my Gmail inbox and Google Calendar. Can you set up the Google integration so you can access both? I need read access to email and calendar.
Claude will walk you through the authentication steps. Once connected, test it:
Show me my calendar for the next 3 days. Show me my last 10 emails.
If both work, you’re ready. Start a fresh conversation for the setup below.
Step 0: Prime Claude for the Setup
Start a fresh conversation and paste this first — it tells Claude to expect a multi-step setup:
I'm going to walk you through a multi-step setup for a daily morning briefing. I'll give you each piece one at a time — don't try to jump ahead or do everything at once. Wait for my prompt at each step, confirm what you did, and I'll give you the next one. We'll build up a set of files together, then test and schedule the whole thing at the end.
Note: Claude will ask for permission the first time it tries to write a file, read your email, access your calendar, or fetch a web page. Click “Always Allow” each time these pop up. You’ll see a few of these during setup and the first test run — after that, everything runs without prompts.
Step 1: Configure Delivery
Tell Claude where to send the brief and what timezone you’re in. These two settings are needed for every brief, regardless of which sections you set up. Paste this:
I want to configure delivery settings for my morning brief. Save the following two values to a file called `brief-config.md`: 1. Email address — where the morning brief should be delivered each day 2. Timezone — my local timezone in IANA format (e.g., America/New_York, America/Los_Angeles, Europe/London) Ask me for each value, then show me the file and confirm before saving.
Step 2: Create the Morning Brief Instructions
This step builds the core instructions file that Claude will follow every morning. Paste these prompts in order — Claude will assemble them into one file.
Step 2a — Create the file + Calendar & Email sections
I want to create a scheduled daily task called 'morning-brief.' Save the following as a file called morning-brief-instructions.md so the scheduled task can reference it every morning. I'll give you the content in parts — save everything into one file. TONE Keep the brief upbeat, encouraging, and forward-looking. This brief should feel like a helpful friend giving you a morning rundown, not a cold report. Frame calendar and email summaries as "here's what's ahead" rather than "here's what you have to deal with." MORNING BRIEF FORMAT Generate a daily briefing in plain text using Unicode box-drawing characters. Use the timezone from brief-config.md for all times. SECTION 1 — CALENDAR Pull today + next 2-3 days from Google Calendar. Include event title, time, location, attendees, and relevant details. If a day is clear, say "Clear." Flag conflicts, early mornings, or anything needing prep. SECTION 2 — EMAIL (LAST 24 HOURS) Scan Gmail inbox for the last 24 hours. Split into: - Worth acting on — requires response, has a deadline, confirms something important, delivers something ordered. One bullet per item with a brief note on why it matters. - Noise skipped — newsletters, promos, digests, automated notifications, marketing. One line, comma-separated list of sender/subject. If there are no actionable emails, say "Nothing requiring action." If there are no noise emails, say "Inbox was quiet."
Step 2b — Error handling + Output template
After Claude confirms Step 2a is saved, paste this:
Continue adding to morning-brief-instructions.md: ERROR HANDLING - If Gmail or Calendar authentication has expired, note it at the top of the brief: "⚠️ Gmail/Calendar auth expired — re-authenticate to restore this section." - Never fabricate calendar events or email summaries. If data is unavailable, say so. OUTPUT TEMPLATE MORNING BRIEF — [DAY OF WEEK], [FULL DATE] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 📅 CALENDAR ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ [calendar content] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 📬 EMAIL — LAST 24 HOURS ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Worth acting on: • [item] • [item] Noise skipped: [comma-separated list] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Generated [DATE]
Step 2c — Confirm Claude understood
After Claude saves the complete file, verify it internalized everything:
Read back morning-brief-instructions.md and confirm you understand the format and the error handling rules. Summarize what you'll do for each section.
Step 3: Add Career Search (Optional — only if you’re actively job hunting)
If you’re not job hunting, skip this entire step and jump to Step 4. The brief will run with just calendar and email.
This step adds two new sections to your morning brief — Section 3 (Career Search via public ATS APIs) and Section 4 (LinkedIn Search via the public guest API). Together they fetch real job listings, score them against your resume and preferences, and dedupe across sources.
Step 3a — Add your resume and career preferences
Paste this into Claude:
I'm going to give you my resume. Save it as resume.md so you can reference it for daily job matching.
Attach, drop, or paste your resume. Claude will save it as resume.md.
After the resume is saved, paste this:
Now I want you to interview me about my career preferences — what I'm actually looking for, not just what I've done. Ask me questions one at a time, and when we're done, generate a career-preferences.md file from my answers. Cover these topics: - Location — Where I'd want to work, cities or regions I'd consider, willingness to relocate - Work mode — Remote, hybrid, or on-site preference, and whether it's a deal-breaker or just a preference - Level & compensation — Whether I'm looking to stay lateral, step up, or open to a step back for the right opportunity. Any compensation floor. - Skills & direction — What I want to do more of, what I'm done with, and where I see my career heading - Company & culture — Startup vs. BigCo preference, industries or sectors to avoid - Logistics — Travel tolerance, hard deal-breakers, and whether I'm actively looking or just passively monitoring After each answer, ask a brief follow-up if my answer is vague or could be more specific. When we're done, show me the generated career-preferences.md and ask me to confirm before saving.
Just answer naturally. When the interview is done, Claude will show you career-preferences.md for approval before saving.
These preferences sharpen the scoring. Without them, Claude can only match on what you’ve done. With them, it matches on what you actually want.
Step 3b — Save the starter careers-endpoints.md
Most company careers pages are protected by Cloudflare or Akamai bot detection, or are JavaScript-rendered single-page apps that return an empty shell to a server-side fetch. Direct scraping is unreliable.
The fix: most companies post jobs through a small number of Applicant Tracking Systems (Greenhouse, Lever, Ashby, Workday) that expose public JSON APIs. The list below is pre-verified — every endpoint returned live job data when this guide was written. For BigCo holdouts (Google, Microsoft, Apple, Meta, etc.) that don’t expose APIs, Section 4 (LinkedIn) covers them, since they all post their roles to LinkedIn anyway.
Paste this into Claude:
Save the following content as `careers-endpoints.md`. This is the company-to-ATS-endpoint map my morning brief will use to fetch jobs each day:
| Company | ATS | Endpoint |
|---|---|---|
| Anthropic | Greenhouse | https://boards-api.greenhouse.io/v1/boards/anthropic/jobs |
| OpenAI | Ashby | https://api.ashbyhq.com/posting-api/job-board/openai |
| NVIDIA | Workday | https://nvidia.wd5.myworkdayjobs.com/wday/cxs/nvidia/NVIDIAExternalCareerSite/jobs |
| CoreWeave | Greenhouse | https://boards-api.greenhouse.io/v1/boards/coreweave/jobs |
| Scale AI | Greenhouse | https://boards-api.greenhouse.io/v1/boards/scaleai/jobs |
| Crusoe Energy | Ashby | https://api.ashbyhq.com/posting-api/job-board/crusoe |
| Lambda | Ashby | https://api.ashbyhq.com/posting-api/job-board/lambda |
| Cloudflare | Greenhouse | https://boards-api.greenhouse.io/v1/boards/cloudflare/jobs |
| Anduril | Greenhouse | https://boards-api.greenhouse.io/v1/boards/andurilindustries/jobs |
The four ATS providers above all expose public JSON endpoints with documented patterns:
- Greenhouse — https://boards-api.greenhouse.io/v1/boards/{slug}/jobs (GET)
- Lever — https://api.lever.co/v0/postings/{slug}?mode=json (GET)
- Ashby — https://api.ashbyhq.com/posting-api/job-board/{slug} (GET)
- Workday — https://{tenant}.wdN.myworkdayjobs.com/wday/cxs/{tenant}/{site}/jobs (POST with {"appliedFacets":{},"limit":20,"offset":0,"searchText":""})
Confirm the file is saved and let me know how many companies are in it.
Want to add or remove companies? See the Maintenance section below.
Step 3c — Add Section 3 (Career Search) to the instructions
After endpoints are saved, paste this:
Continue adding to morning-brief-instructions.md:
CADENCE UPDATE
Sections 3 (Career Search) and 4 (LinkedIn Search) only run on Monday and Thursday. On other days, skip them and add a line at the end: "Career search runs Mon & Thu — next run [day]."
SECTION 3 — CAREER SEARCH
Read the company list and endpoints from `careers-endpoints.md`. For each company, fetch open roles using the listed ATS:
- Greenhouse / Lever / Ashby endpoints — GET the JSON endpoint and parse the job list directly.
- Workday endpoints — POST with {"appliedFacets":{},"limit":50,"offset":0,"searchText":""} and parse the jobPostings array.
If an endpoint returns an error or empty data, skip it and add the company to an "Unreachable" list at the bottom of this section. Do not invent jobs.
Score each role against `resume.md` and `career-preferences.md`. Filter out roles that violate any deal-breakers (wrong work mode, excluded industries, etc.) before scoring.
Process companies in batches of 5. Complete each batch before starting the next. If you hit a timeout or error, report what completed and continue with the remaining companies.
Scoring rubric — score each role on 5 dimensions (1 point each, sum for total):
- Title match (1 pt) — Role title aligns with current or target title from resume/preferences
- Scope/level match (1 pt) — Seniority, team size, budget responsibility, or IC depth is comparable
- Domain match (1 pt) — Industry, function, or technical domain overlaps with experience or stated direction
- Location match (1 pt) — Role is in a preferred city/region, or is remote-eligible when remote is preferred
- Work mode match (1 pt) — Remote/hybrid/on-site aligns with preferences
Only show roles scoring 3/5 or higher.
Output format for each match:
- Job title — Score: X/5 (dimensions matched: title, scope, domain, etc.)
- Location | Department — if remote-eligible or remote-friendly, add a 🏠 emoji next to the location
- One-line "Why" noting which dimensions matched and which didn't
- Direct application link
Group into "STRONG MATCHES (4-5/5)" and "REASONABLE MATCHES (3/5)." Report total jobs reviewed across all reachable companies, total matches found, and any unreachable companies. If there are zero matches, say "No matches today" — do not stretch to include weak matches.
IMPORTANT: Never fabricate jobs. If a company is unreachable, list it and move on. Quality over quantity.
Step 3d — Add Section 4 (LinkedIn Search) to the instructions
After Section 3 is saved, paste this:
Continue adding to morning-brief-instructions.md: SECTION 4 — LINKEDIN SEARCH Section 4 covers everything Section 3 doesn't — BigCo employers (Google, Microsoft, Apple, Meta, Oracle, etc.) and the long tail of smaller companies. It uses LinkedIn's public guest jobs API (no auth needed) to fetch real listings, then scores them using the same rubric as Section 3. ENDPOINT Base URL: https://www.linkedin.com/jobs-guest/jobs/api/seeMoreJobPostings/search Query parameters to build from career-preferences.md: - keywords — URL-encoded boolean expression. Use AND, OR, quotes for exact phrases, parentheses for grouping. Build from skills/direction/target titles in career-preferences.md. - location — city, region, or "United States" based on preferences - f_WT — work mode filter: 1=onsite, 2=remote, 3=hybrid (omit if any is acceptable) - f_TPR=r604800 — past 7 days only (keeps results fresh; on Mon use r259200, Thu use r345600 to avoid showing the same week twice) - f_E — experience level: 4=mid-senior, 5=director, 6=executive (pick what matches preferences) - start=0 — pagination QUERY STRATEGY Generate 1-3 targeted queries based on the user's preferences (e.g., one for primary target title, one for adjacent/stretch role, one for specific domain). Don't run more than 3 queries per brief — LinkedIn rate-limits aggressive callers. PARSING The endpoint returns HTML job cards (not JSON). Each card includes: - data-entity-urn (the LinkedIn job ID) - Job title, company, location - Posting date / "X days ago" - Apply URL Parse these fields from each card. If the HTML structure has changed and parsing fails, note it: "⚠️ LinkedIn parser may need updating — card markup may have changed." Do not fabricate jobs. SCORING & DEDUP Score each job against resume.md and career-preferences.md using the same 5-dimension rubric as Section 3. Note: domain match is title-only since LinkedIn search responses don't include full descriptions — be appropriately conservative with that dimension. Dedup against (a) jobs already shown in Section 3 of this brief and (b) seen-jobs.md from prior runs. Only show roles scoring 3/5 or higher. OUTPUT Use the same STRONG / REASONABLE matches grouping as Section 3. Cap total LinkedIn matches shown at 10 per brief — if more qualify, show the top 10 by score and note "X additional matches suppressed for length." Report total LinkedIn jobs reviewed and total queries run.
Step 3e — Add deduplication, error handling, and output template additions
After Section 4 is saved, paste this final piece:
Finish updating morning-brief-instructions.md with these additions:
DEDUPLICATION
Maintain a file called ~/.claude/morning-brief/seen-jobs.md. Dedup applies across both Section 3 (ATS) and Section 4 (LinkedIn) — the same job often appears in both, and should only be shown once per brief. Use job title + company (case-insensitive) as the dedup key.
Before including a match in either section, check if the same job title + company combination already exists in seen-jobs.md. If it does, skip it — unless the posting date is newer, which indicates a repost worth resurfacing. Within a single brief, also dedup between Section 3 and Section 4 — if a Section 3 match is already shown, suppress the equivalent in Section 4.
After each run, append any new matches to seen-jobs.md with the date first seen, formatted as:
[2026-04-17] Senior PM — Anthropic
[2026-04-17] Staff Engineer — Stripe
If seen-jobs.md doesn't exist yet, create it on the first run.
CAREER SEARCH ERROR HANDLING (additions to existing ERROR HANDLING block)
- If a careers-endpoints.md entry returns an error or empty data, skip it and list unreachable companies at the bottom of Section 3.
- If the LinkedIn guest API returns an error, rate-limits, or returns 0 cards across all queries, note it at the top of Section 4: "⚠️ LinkedIn fetch failed — check rate limits or endpoint changes" and continue with the rest of the brief.
- Never fabricate job listings.
TONE ADDITIONS
Career searching can be stressful. Celebrate good matches. Keep "no matches today" low-key and positive ("nothing jumped out today — tomorrow's a new batch").
OUTPUT TEMPLATE ADDITIONS
Insert the following blocks into the OUTPUT TEMPLATE between the existing EMAIL section and the "Generated [DATE]" footer:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🏢 CAREER SEARCH
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
~[N] jobs reviewed across [N] companies · [N] matches found
STRONG MATCHES (4-5/5)
──────────────────────
[Job Title] — Score: X/5 (title, scope, domain, location, work mode)
Location: [Location] 🏠 | Dept: [Dept]
Why: [which dimensions matched/missed]
Link: [url]
REASONABLE MATCHES (3/5)
─────────────────────────
[Job Title] — Score: X/5 (title, domain, work mode)
Location: [Location] 🏠 | Dept: [Dept]
Why: [which dimensions matched/missed]
Link: [url]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🔍 LINKEDIN SEARCH
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
~[N] jobs reviewed across [N] queries · [N] matches found
STRONG MATCHES (4-5/5)
──────────────────────
[Job Title] — Score: X/5 (title, scope, domain, location, work mode)
Company: [Company] | Location: [Location] 🏠
Why: [which dimensions matched/missed]
Link: [LinkedIn job URL]
REASONABLE MATCHES (3/5)
─────────────────────────
[Job Title] — Score: X/5 (title, location, work mode)
Company: [Company] | Location: [Location] 🏠
Why: [which dimensions matched/missed]
Link: [LinkedIn job URL]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Also update the footer line to read:
Generated [DATE]
Resume last updated: [date from resume.md] · Preferences last updated: [date from career-preferences.md]
Step 3f — Confirm Claude understood the additions
Read back morning-brief-instructions.md and confirm you understand the career search sections, the scoring rubric, the deduplication logic, and the updated error handling. Summarize what you'll do for Sections 3 and 4.
Step 4: Test It
Paste this into Claude:
Run a full test of the morning brief using the instructions in morning-brief-instructions.md (and any supporting files that exist: brief-config.md, careers-endpoints.md, resume.md, career-preferences.md). Include every section that's defined in the instructions file, regardless of what day it is. Give me the full output.
Review the output. Check:
- Calendar events are correct and times are in your timezone
- Email filtering makes sense (right things in “actionable” vs “noise”)
- (career search only) ATS endpoints returned real jobs; any unreachable companies are noted, not fabricated
- (career search only) LinkedIn fetch returned real jobs (not duplicated against Section 3)
- (career search only) Job matches are relevant and properly scored against your preferences
- Links work
If anything needs tuning, tell Claude what to fix and have it update the relevant file.
Delivery notes for the test run:
- Email — During the manual test, Claude may create a draft in your Gmail drafts folder instead of sending directly. That’s normal. When the scheduled task runs autonomously, it should send. Check your drafts folder to verify formatting looks right, and confirm on the first real scheduled run that it sends rather than drafts.
- Dispatch (mobile push) — This only fires during scheduled task runs, not when running manually in conversation. You won’t see the push notification until the first real scheduled run.
Step 5: Schedule It
Once you’re happy with the output, paste this:
Schedule the morning brief to run every day at 6:30 AM (using the timezone in brief-config.md), 7 days a week. It should read the instructions from morning-brief-instructions.md, plus any supporting files that exist (brief-config.md, careers-endpoints.md, resume.md, career-preferences.md), then generate and deliver the brief. Send the output to the email address in brief-config.md and deliver it via Claude Dispatch so I also get it as a mobile notification. Call the scheduled task 'morning-brief'.
Claude will set up the scheduled task. Confirm it’s scheduled:
Show me my scheduled tasks.
Important: The first scheduled run will pause to ask for tool approvals (Gmail, Calendar, web access). To pre-approve everything now, click “Run now” from the Scheduled section in the sidebar. Let it run through and approve each permission it asks for. After that, future runs will be fully autonomous.
Once confirmed, paste this final prompt to let Claude know the setup is complete:
Setup is complete. Do a final check — read every file you created (morning-brief-instructions.md, brief-config.md, plus any of resume.md, career-preferences.md, careers-endpoints.md that exist), confirm they're consistent with each other, and let me know if anything looks off. If it all checks out, we're done.
Maintenance
Update delivery email or timezone:
Update brief-config.md — [describe the change].
Add career search later: If you started with calendar + email only and now want to enable Sections 3 and 4:
I want to add the career search sections to my morning brief. Walk me through Step 3 from the setup guide — resume + preferences, ATS endpoints, and adding Sections 3 and 4 to morning-brief-instructions.md.
Remove career search: If you want to stop the career sections (e.g., new role landed, taking a break):
Remove Sections 3 and 4 from morning-brief-instructions.md, remove the Career Search and LinkedIn output template blocks, and delete careers-endpoints.md, resume.md, career-preferences.md, and seen-jobs.md. Keep brief-config.md, calendar, and email as they are.
Update your resume: When your role or responsibilities change:
Update my resume in resume.md — [describe changes].
Update your preferences: When your career direction or constraints change:
Update my career preferences in career-preferences.md — [describe changes].
Add a company: To add a new company to the career search:
Add [Company Name] to careers-endpoints.md. Their careers page is [URL]. Try the standard ATS patterns (Greenhouse boards-api.greenhouse.io/v1/boards/{slug}/jobs, Ashby api.ashbyhq.com/posting-api/job-board/{slug}, Lever api.lever.co/v0/postings/{slug}?mode=json, Workday {tenant}.wdN.myworkdayjobs.com/wday/cxs/{tenant}/{site}/jobs) — confirm the endpoint returns real JSON job data with a quick test fetch before adding it. If none of the standard ATS patterns work, skip the company and tell me — direct-scraping a custom careers system is rarely worth the trouble.
Remove a company:
Remove [Company Name] from careers-endpoints.md.
Refresh endpoints: ATS providers occasionally change URLs or companies switch ATS vendors. If you start seeing “unreachable” for a company that used to work:
Re-verify the endpoint for [Company Name] in careers-endpoints.md.
Adjust the email filter: If something keeps landing in the wrong category:
Update the morning brief instructions — emails from [sender] should always be in 'worth acting on' (or 'noise').
Files Created
~/.claude/morning-brief/ ├── morning-brief-instructions.md # Format, scoring rubric, section logic (always) ├── brief-config.md # Email + timezone for delivery (always) ├── careers-endpoints.md # ATS endpoints per company (career search only) ├── resume.md # Your resume for job matching (career search only) ├── career-preferences.md # Location, work mode, direction, deal-breakers (career search only) └── seen-jobs.md # Dedup log — auto-maintained, don't edit (career search only)
If you set up calendar + email only, you’ll just have morning-brief-instructions.md and brief-config.md. The other files appear when you enable career search.
Everything is prompt-driven. No CLI commands, no config files, no code. Just tell Claude what you want.
Source on GitHub: mcornelia/claude-morning-brief. Questions or improvements? Reach out.