Briefed
/install briefed
Briefed
A daily newsletter digest pipeline + local web reader. Gmail → Haiku summaries → web app → notification ping.
Architecture
[Gmail]
↓ pre-fetch.py (fetches, filters, extracts compact metadata)
[newsletter-inbox.json]
↓ Haiku cron agent (reads compact JSON, writes AI summaries)
[newsletter-today.json]
↓ fetch-bodies.py (adds full HTML email bodies)
[newsletter-today.json + bodies]
↓ Express web reader (default port 3001)
[Notification ping → user opens reader]
Why split fetch/summarise? Raw Gmail API JSON overflows Haiku's context. Python handles data wrangling; Haiku handles cognition.
Security & Scope
- Gmail access is read-only (
gmail.readonly). - OAuth token is stored locally at
~/.openclaw/workspace/briefed-gmail-token.json(orBRIEFED_GMAIL_TOKEN_FILE). - The workflow should only read/write the following workspace files:
newsletter-inbox.jsonnewsletter-today.jsonnewsletter-interests.jsonnewsletter-notes.jsonreading-list.md
- Do not send newsletter content to external endpoints other than the configured model provider and user-selected notification channel.
Prerequisites
- Python 3.9+
- Python deps for Gmail API (
google-api-python-client,google-auth,google-auth-oauthlib) - A Google OAuth Desktop client JSON file (for Gmail read-only auth)
- Node.js ≥18 (for the reader web app)
claude-haiku-4-5on the OpenClaw models allowlist- A notification channel configured in OpenClaw (Telegram, Discord, etc.)
Setup
1. Install Python dependencies
cd ~/.openclaw/workspace/briefed
python3 -m pip install -r scripts/requirements.txt
2. Configure Gmail OAuth
Create a Google Cloud OAuth Desktop app and download the client JSON, then set:
export BRIEFED_GMAIL_CLIENT_SECRET=~/client_secret.json
On first script run, Briefed opens a browser OAuth flow and stores a reusable token at:
~/.openclaw/workspace/briefed-gmail-token.json
3. Deploy the reader app
# Copy the reader to the workspace
cp -r assets/reader/ ~/.openclaw/workspace/briefed/
cd ~/.openclaw/workspace/briefed
npm install
4. Configure Gmail token paths (optional)
Defaults (works for most users):
- Token file:
~/.openclaw/workspace/briefed-gmail-token.json - Client secret:
~/client_secret.json
Override via env vars if needed:
export BRIEFED_GMAIL_CLIENT_SECRET=~/path/to/client_secret.json
export BRIEFED_GMAIL_TOKEN_FILE=~/.openclaw/workspace/briefed-gmail-token.json
5. Configure interests
Create ~/.openclaw/workspace/newsletter-interests.json (or let it be auto-created on first run):
{
"version": 1,
"topics": { "ai": 0.9, "startups": 0.8, "design": 0.75 },
"signals": [],
"sources": {}
}
6. Start the reader
Run manually if you prefer no persistence. LaunchAgent is optional convenience for auto-start.
# Quick test
node ~/.openclaw/workspace/briefed/server.js
# Persistent — create ~/Library/LaunchAgents/ai.openclaw.briefed.plist
LaunchAgent plist template:
\x3C?xml version="1.0" encoding="UTF-8"?>
\x3C!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
\x3Cplist version="1.0">\x3Cdict>
\x3Ckey>Label\x3C/key>\x3Cstring>ai.openclaw.briefed\x3C/string>
\x3Ckey>ProgramArguments\x3C/key>\x3Carray>
\x3Cstring>/usr/local/bin/node\x3C/string>
\x3Cstring>/Users/YOUR_USER/.openclaw/workspace/briefed/server.js\x3C/string>
\x3C/array>
\x3Ckey>EnvironmentVariables\x3C/key>\x3Cdict>
\x3Ckey>BRIEFED_GMAIL_CLIENT_SECRET\x3C/key>\x3Cstring>/Users/YOUR_USER/client_secret.json\x3C/string>
\x3Ckey>BRIEFED_GMAIL_TOKEN_FILE\x3C/key>\x3Cstring>/Users/YOUR_USER/.openclaw/workspace/briefed-gmail-token.json\x3C/string>
\x3C/dict>
\x3Ckey>RunAtLoad\x3C/key>\x3Ctrue/>
\x3Ckey>KeepAlive\x3C/key>\x3Ctrue/>
\x3Ckey>WorkingDirectory\x3C/key>\x3Cstring>/Users/YOUR_USER/.openclaw/workspace/briefed\x3C/string>
\x3Ckey>StandardOutPath\x3C/key>\x3Cstring>/tmp/briefed.log\x3C/string>
\x3Ckey>StandardErrorPath\x3C/key>\x3Cstring>/tmp/briefed.log\x3C/string>
\x3C/dict>\x3C/plist>
launchctl load ~/Library/LaunchAgents/ai.openclaw.briefed.plist
7. Create the daily cron job
Use the OpenClaw cron tool with this agent prompt (fill in the placeholders):
Run my daily newsletter digest. Follow these steps exactly:
## Step 1 — Pre-fetch emails
Run: python3 ~/.openclaw/workspace/briefed/scripts/pre-fetch.py
## Step 2 — Read the compact inbox
Read: ~/.openclaw/workspace/newsletter-inbox.json
## Step 3 — Write newsletter-today.json with AI summaries
For each newsletter, write to **only** this file: ~/.openclaw/workspace/newsletter-today.json.
Do not modify any other files in this step.
Use the snippet field to write real summaries — do NOT just repeat the subject line.
Score by interest: (adjust topics and weights to match your interests)
ai/ml=0.9, startups=0.85, design=0.8, finance=0.75, general=0.6
Schema per story:
{ "id", "rank", "source", "subject", "headline", "summary", "bullets": [], "threadId", "gmailUrl", "score", "body": "" }
## Step 4 — Fetch HTML bodies
Run: python3 ~/.openclaw/workspace/briefed/scripts/fetch-bodies.py
## Step 5 — Send notification
Send (via your configured channel):
"📬 Today's digest is ready — \x3CN> stories waiting.\
→ http://YOUR_HOST:3001"
## Step 6 — Final reply
📬 *Briefed — [DD Mon YYYY]* · \x3CN> stories
*\x3Crank>. \x3CSource>* — \x3CHeadline>
\x3COne sentence summary>
(repeat for all stories)
_Open the reader → http://YOUR_HOST:3001_
Before enabling cron, run this once manually to complete OAuth in a browser:
python3 ~/.openclaw/workspace/briefed/scripts/pre-fetch.py
Cron schedule: 0 7 * * * (7am daily), model: anthropic/claude-haiku-4-5, delivery: announce.
Data Files
All data files live in ~/.openclaw/workspace/:
| File | Purpose |
|---|---|
newsletter-inbox.json |
Compact pre-fetched email metadata (ephemeral) |
newsletter-today.json |
Today's stories with summaries + HTML bodies |
newsletter-interests.json |
Topic weights + vote/open signals |
newsletter-notes.json |
Per-story user notes |
reading-list.md |
Saved/bookmarked stories |
Reader API
| Endpoint | Method | Purpose |
|---|---|---|
/api/today |
GET | All stories (bodies stripped) |
/api/story/:id |
GET | Single story with full HTML body |
/api/vote |
POST | { storyId, vote: "up"|"down"|"open" } |
/api/save |
POST | { storyId } — adds to reading-list.md |
/api/note |
POST | { storyId, note } |
/api/notes |
GET | All notes |
Filtering Transactional Email
scripts/pre-fetch.py has two tunable lists near the top:
SKIP_SUBJECT_PATTERNS— subject substrings that flag an email as transactionalSKIP_SENDERS— sender names that are always transactional (e.g. banks, shops)
Tune these when transactional emails slip through.
Branding
The reader shows "Briefed" with a blue "B" logo by default. To customise, edit public/index.html and public/icon.svg.
- 确保已安装 OpenClaw(本地或 Docker 部署)
- 在对话框中输入安装命令:
/install briefed - 安装完成后,直接呼叫该 Skill 的名称或使用
/briefed触发 - 根据 Skill 的参数说明提供必要输入,即可获得结构化输出
Briefed 是什么?
Set up and run a personal AI newsletter intelligence system called Briefed. Fetches Gmail newsletters daily, uses Claude Haiku to extract article summaries,... 它是一个面向 Claude Code / OpenClaw 的 AI Agent Skill 插件,目前累计下载 438 次。
如何安装 Briefed?
在 OpenClaw 或 Claude Code 对话框中运行命令「/install briefed」即可一键安装,无需额外配置。
Briefed 是免费的吗?
是的,Briefed 完全免费(开源免费),可自由下载、安装和使用。
Briefed 支持哪些平台?
Briefed 跨平台运行,可在任意部署了 OpenClaw / Claude Code 的环境中使用(cross-platform)。
谁开发了 Briefed?
由 jamesnation(@jamesnation)开发并维护,当前版本 v1.1.2。