Installs into .claude/skills of the current project.
Are you the author of Tweet Digest?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/aeonfun-tweet-digest)
---
type: Skill
name: Tweet Digest
category: basics
description: Account-based digest of recent tweets from tracked X/Twitter accounts. Sibling to fetch-tweets (keyword) and tweet-roundup (topic).
var: ""
tags: [social]
requires: [TWITTER_API_KEY, XAI_API_KEY?]
---
> **${var}** — Optional. If set, restrict to that single account (or topic filter). If empty, processes every account in `memory/topics/tracked-accounts.yml`.
This skill is the **account-based** sibling in the tweet-fetcher family:
| Skill | Axis | Input |
|---|---|---|
| `fetch-tweets` | keyword / query | `${var}` is the search query |
| `tweet-roundup` | topic | groups recent tweets by topic |
| `tweet-digest` (this) | **account** | reads a list of handles from `memory/topics/tracked-accounts.yml` |
Use this skill when you care about "what did *these specific people* post" rather than "what's anyone saying about X."
## Voice
If `soul/SOUL.md` and `soul/STYLE.md` are populated, read both and match the operator's voice for the per-tweet one-sentence takes. If they are empty templates or absent, write the takes in a clear, direct, neutral tone — no hedging, no editorializing beyond what the tweet itself says.
## Config
Reads `memory/topics/tracked-accounts.yml`. If the file is missing or `accounts: []`, log `TWEET_DIGEST_NO_CONFIG` and exit (no notification).
```yaml
# memory/topics/tracked-accounts.yml
accounts:
- handle: vitalikbuterin
why: ethereum core thinking
- handle: balajis
why: macro + tech narratives
- handle: <handle>
why: <one-line reason — used to give the digest grouping context>
```
The `why` field is optional but useful — it's the grouping/context label in step 2.
## Steps
Read `memory/MEMORY.md` for context and the last 2 days of `memory/logs/` to dedup recent tweets.
### 1. Fetch recent tweets per account
For each `handle` in the config (or just the one from `${var}` if set):
**Path A - twitterapi.io (primary).** `/user/last_tweets` returns structured tweet objects (exact engagement counts, real permalinks, parsed fields) in ~700ms - no fabrication risk. It has no server-side date filter, so keep the last 3 days client-side on `.createdAt`. Auth via `./secretcurl` with the literal `{TWITTER_API_KEY}` placeholder (never `$TWITTER_API_KEY`; see CLAUDE.md -> Network & Secrets):
```bash
SINCE=$(date -u -d '3 days ago' +%Y-%m-%d 2>/dev/null || date -u -v-3d +%Y-%m-%d)
HTTP=$(./secretcurl -m 30 -s -o /tmp/tw-td.json -w '%{http_code}' -G "https://api.twitterapi.io/twitter/user/last_tweets" \
--data-urlencode "userName=$HANDLE" -H "X-API-Key: {TWITTER_API_KEY}")
echo "twitterapi http=$HTTP"
# on HTTP 200: last-3-day originals (createdAt is Twitter native format; strptime normalizes to a date), skip replies/RTs
jq -r --arg since "$SINCE" '
.data.tweets[]
| select((.isReply // false) | not)
| (try (.createdAt | strptime("%a %b %d %H:%M:%S %z %Y") | strftime("%Y-%m-%d")) catch (.createdAt[0:10])) as $d
| select($d >= $since)
| [.author.userName, $d, .likeCount, .retweetCount, .replyCount, .url, .text] | @tsv' /tmp/tw-td.json
```
On `HTTP=200` with parsed rows, take the 5 most interesting or substantive tweets for that handle; paginate with `&cursor=<next_cursor>` only if you need older in-window tweets.
**Path B - xAI Grok `x_search` (fallback).** Only if a handle's Path A returned non-2xx, empty, or timed out (or `TWITTER_API_KEY` is unset). Call Grok's `x_search` **in-run** with `./secretcurl` (the literal `{XAI_API_KEY}` placeholder - never `$XAI_API_KEY`; see CLAUDE.md -> Network & Secrets). Capture the HTTP status and print `http=<code>` before parsing:
```bash
PROMPT="Search X for the latest tweets from ${HANDLE} in the last 3 days. Return the 5 most interesting or substantive tweets. For each: full text, date, direct link (https://x.com/${HANDLE}/status/ID). Skip retweets of others."
jq -n --arg p "$PROMPT" '{model:"grok-4-1-fast", input:[{role:"user",content:$p}], tools:[{type:"x_search"}]}' > /tmp/xai-td.json
HTTP=$(./secretcurl -m 60 -s -o /tmp/xai-td-out.json -w '%{http_code}' -X POST "https://api.x.ai/v1/responses" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer {XAI_API_KEY}" \
-d @/tmp/xai-td.json)
echo "http=$HTTP"
```
Then parse `/tmp/xai-td-out.json` for the tweets. If neither `TWITTER_API_KEY` nor `XAI_API_KEY` is set, log `TWEET_DIGEST_NO_KEY: skill requires TWITTER_API_KEY or XAI_API_KEY` and exit (no notification). On a non-2xx `http`, a `--max-time` timeout, or a 200 with an empty body on both paths, record the real reason (`http-<code>` / `timeout` / `empty`) and skip that handle - never blame a "sandbox".
**Dedup:** grep the last 2 days of `memory/logs/` for `https://x.com/` URLs already reported. Drop any candidate URL that's already been seen.
### 2. Group by theme, not by account
Walk the candidate set across all accounts. Identify 2–4 themes (e.g. "L2 design decisions", "macro / rates", "AI model releases", "regulation"). Each tweet maps to one theme. A `why:` label from the config can seed theme naming when an account is a single-topic feed.
### 3. Write a one-sentence take per notable tweet
The take states **what the tweet says**, not your opinion of it. Voice per the Voice section above.
### 4. Format and notify
Send via `./notify` (under 4000 chars):
```
*Tweet Digest — ${today}*
*Theme: <theme>*
@handle: <one-sentence summary> — [link](url)
@handle: <one-sentence summary> — [link](url)
*Theme: <theme>*
...
```
### 5. Log
Append to `memory/logs/${today}.md` with the tweet URLs reported (so the next run can dedup). If no notable tweets found across all tracked accounts: log `TWEET_DIGEST_OK` and end (no notification).
## Fetching - in-run, no prefetch
Auth'd calls run **in-run** via `./secretcurl` with a literal `{ENV}` placeholder - twitterapi.io (`{TWITTER_API_KEY}`, primary) and X.AI Grok (`{XAI_API_KEY}`, fallback); see step 1 and CLAUDE.md -> Network & Secrets. There is **no** prefetch/cache step - the retired `.xai-cache/` + `scripts/prefetch-xai.sh` pattern no longer exists; do not reference it.
## Environment Variables
- `TWITTER_API_KEY` - primary. twitterapi.io key (`X-API-Key` header) for structured tweet fetches via `/user/last_tweets`.
- `XAI_API_KEY` - optional fallback. X.AI API key for Grok's `x_search` tool when twitterapi.io is unavailable.