Weekly Report Builder
Drafts your Friday report from the week's signals.
— James, who's been doing this 20+ years (3 at Meta). More →
A small assistant that reads two things you already produce all week without trying: the mail you sent and the meetings you sat in. Friday morning it hands you a drafted status report built from both, in your inbox before you’ve opened a blank doc. You edit, you don’t write. You set it up once, you own it, and it runs on your own Google account.
What you’ll need
- A Gmail / Google Workspace account with your work calendar on it.
- An Anthropic API key (this is what powers the drafting). You add a few dollars of credit once; the running cost is in the table further down.
- A spare half hour and the willingness to copy and paste.
Step 1 — Get your AI key
Go to console.anthropic.com, sign in, open API Keys, and click Create Key. Copy the key it gives you (starts with sk-ant-) and keep it for a minute. Add a small amount of billing credit while you’re there. If you’ve never made an Anthropic account before, this step is most of the build time.
Step 2 — Open the script editor
Go to script.google.com, click New project. Delete the placeholder code already in the box so it’s empty.
Step 3 — Paste this in
Paste the whole block below into the empty editor.
// ============================================================
// WEEKLY REPORT BUILDER - by autohmate
// Reads your week's sent mail + calendar, drafts your Friday
// report, and emails you the draft Friday morning.
// ============================================================
// 1) PASTE YOUR ANTHROPIC API KEY BETWEEN THE QUOTES:
const API_KEY = "PASTE-YOUR-KEY-HERE";
// 2) IN PLAIN ENGLISH, TELL IT HOW YOU REPORT:
const REPORT_STYLE = `
You are drafting my Friday status report from this week's
signals: the mail I sent and the meetings I sat in.
Sections: Shipped / In progress / Blockers / Next week.
Short concrete lines, no fluff. If something I sent mail
about looks stalled or unanswered, put it under Blockers.
If you are not sure where something goes, put it under
In progress with a question mark.
`;
// 3) DAYS TO LOOK BACK EACH RUN (7 = the working week):
const LOOKBACK_DAYS = 7;
// ----- leave everything below this line alone -----
function draftWeeklyReport() {
var cutoff = new Date(Date.now() - LOOKBACK_DAYS * 24 * 3600 * 1000);
var me = Session.getActiveUser().getEmail();
// What you told people this week - your sent mail.
var query = "in:sent after:" + Math.floor(cutoff.getTime() / 1000);
var threads = GmailApp.search(query, 0, 50);
var sent = [];
threads.forEach(function (t) {
t.getMessages().forEach(function (m) {
if (m.getDate() >= cutoff && m.getFrom().indexOf(me) !== -1) {
sent.push(
"TO: " + m.getTo() +
"\nSUBJECT: " + m.getSubject() +
"\nBODY: " + m.getPlainBody().slice(0, 600)
);
}
});
});
// Where your week actually went - your calendar.
var events = CalendarApp.getDefaultCalendar().getEvents(cutoff, new Date());
var meetings = events.map(function (e) {
return e.getStartTime().toDateString() + " - " + e.getTitle();
});
if (sent.length === 0 && meetings.length === 0) {
GmailApp.sendEmail(me, "Weekly report draft - nothing found",
"No sent mail or calendar events in the lookback window.");
return;
}
var prompt =
REPORT_STYLE +
"\n\nTHIS WEEK'S MEETINGS:\n" +
(meetings.length ? meetings.join("\n") : "(none)") +
"\n\nTHIS WEEK'S SENT MAIL:\n\n" +
(sent.length ? sent.join("\n\n---\n\n") : "(none)") +
"\n\nDraft the report now. Start with a single line: " +
"WEEK OF [Monday's date] - DRAFT.";
var res = UrlFetchApp.fetch("https://api.anthropic.com/v1/messages", {
method: "post",
contentType: "application/json",
headers: { "x-api-key": API_KEY, "anthropic-version": "2023-06-01" },
muteHttpExceptions: true,
payload: JSON.stringify({
model: "claude-haiku-4-5-20251001",
max_tokens: 1500,
messages: [{ role: "user", content: prompt }]
})
});
var data = JSON.parse(res.getContentText());
var draft = (data.content && data.content[0])
? data.content[0].text
: "Couldn't generate a draft - check your API key.";
GmailApp.sendEmail(me,
"Weekly report draft - " + new Date().toDateString(), draft);
}Step 4 — Tell it how you report
The part that’s yours is the REPORT_STYLE text near the top. The default gives you Shipped / In progress / Blockers / Next week, which is a sane Friday report almost anywhere. Edit it to match who reads yours. An ops manager reporting upward might write:
My report goes to the VP of Ops. Lead with anything
customer-facing. Group by program, not by day. Keep the
whole thing under 20 lines. Flag anything where I committed
to a date in writing this week.Describe it the way you’d hand the job to someone covering for you. That’s the whole skill.
Step 5 — Paste your key and run it once
Put the key from Step 1 between the quotes on the API_KEY line. Click Save, then Run. Google will ask permission to read your mail and your calendar and to send mail. Click through Allow (it’s your own account giving your own script access). Check your inbox: you should have a draft built from the last seven days. Don’t worry if the first one reads thin on a quiet week; it can only report what the week actually contained.
Step 6 — Make it run every Friday
On the left, click the clock icon (Triggers) → Add Trigger. Choose function draftWeeklyReport, event source Time-driven, type Week timer, day Friday, and an early window like 6–7am. Save. The draft now lands before you sit down Friday.
What this version doesn’t do
This is the demo, on purpose. It turns a blank page into a draft, which is the part of Friday most people put off. Here’s where an off-the-shelf script stops:
- It only sees mail and calendar. Work that lives in Slack, tickets, or shared docs never reaches the draft. If your week happens somewhere else, the draft will be thin there.
- It can’t tell big from small. The ship of the quarter and a rescheduled lunch arrive with equal weight. The judgement is still your edit.
- It drafts to you, not for you. It deliberately emails you the draft instead of sending anything onward. Nothing leaves your account unreviewed.
- No memory between weeks. It can’t say “still blocked, third week running” because it can’t see last week’s report.
The real build pulls from the places your work actually lives, keeps week-over-week memory so blockers age visibly, and learns your edits so the draft drifts toward your voice — the wiring-into-your-week part is what I mean by applied AI. If this little version saves you the blank page, the real one built around your operation is worth a conversation.
The real one goes the way every build goes: I learn your week, we agree the target, I ship it, and I check it stuck.
Same deal as everything I build: if it doesn’t land, you don’t pay for it.
Talk to me →