content-ideas

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

content-ideas

内容创意生成工具

Your For You page. Scrapes every platform where your tracked creators publish, scores what's performing, and turns it into content ideas you can act on. Designed to run daily — each run creates a dated feed under
$CONTENT_HOME/research/
.
The output is a single self-contained HTML page (two tabs: Posts — one sortable, filterable feed merging tracked-account posts and discovered niche outliers — and Ideas) that you can open in a browser, react to, and keep. Reactions are captured for future personalization.
你的专属推荐页面。抓取你追踪的创作者发布内容的所有平台, 对表现出色的内容进行评分,并将其转化为你可以落地执行的内容创意。 本工具设计为每日运行——每次运行都会在
$CONTENT_HOME/research/
目录下创建带日期的内容推送。
输出结果是一个独立的HTML页面(包含两个标签页:帖子——整合了追踪账号帖子和发现的细分领域优质内容的可排序、可筛选推送,以及创意),你可以在浏览器中打开、互动并保存。互动记录会被捕获,用于后续的个性化优化。

Resolve the skill directory

确定技能目录

Everything this skill runs lives under its own folder. The skill installs the same way on Claude Code and Codex, so resolve
SKILL_DIR
against both plugin caches (and a plain repo checkout) once, before anything else:
bash
undefined
本技能运行所需的所有文件都存放在其专属文件夹下。该技能在Claude Code和Codex上的安装方式一致,因此请先一次性确认
SKILL_DIR
对应的插件缓存(以及普通仓库检出路径):
bash
undefined

1) Codex plugin cache, or a repo cloned into ~/.codex/skills/ (latest wins on upgrade).

1) Codex插件缓存,或克隆到~/.codex/skills/目录下的仓库(升级时取最新版本)。

SKILL_DIR="$(ls -d "$HOME/.codex/plugins/cache/"/content-ideas//skills/content-ideas/ "$HOME/.codex/skills/"*/skills/content-ideas/ 2>/dev/null | sort -V | tail -1)" SKILL_DIR="${SKILL_DIR%/}"
SKILL_DIR="$(ls -d "$HOME/.codex/plugins/cache/"/content-ideas//skills/content-ideas/ "$HOME/.codex/skills/"*/skills/content-ideas/ 2>/dev/null | sort -V | tail -1)" SKILL_DIR="${SKILL_DIR%/}"

2) Claude Code plugin cache.

2) Claude Code插件缓存。

if [ -z "$SKILL_DIR" ] || [ ! -f "$SKILL_DIR/scripts/scrape.py" ]; then CLAUDE_ROOT="$(ls -d "$HOME/.claude/plugins/cache/content-ideas/content-ideas/"*/ 2>/dev/null | sort -V | tail -1)" CLAUDE_ROOT="${CLAUDE_ROOT%/}" [ -n "$CLAUDE_ROOT" ] && [ -f "$CLAUDE_ROOT/skills/content-ideas/scripts/scrape.py" ] && SKILL_DIR="$CLAUDE_ROOT/skills/content-ideas" fi
if [ -z "$SKILL_DIR" ] || [ ! -f "$SKILL_DIR/scripts/scrape.py" ]; then CLAUDE_ROOT="$(ls -d "$HOME/.claude/plugins/cache/content-ideas/content-ideas/"*/ 2>/dev/null | sort -V | tail -1)" CLAUDE_ROOT="${CLAUDE_ROOT%/}" [ -n "$CLAUDE_ROOT" ] && [ -f "$CLAUDE_ROOT/skills/content-ideas/scripts/scrape.py" ] && SKILL_DIR="$CLAUDE_ROOT/skills/content-ideas" fi

3) Plugin root passed by the host, or a repo checkout / local dev.

3) 主机传递的插件根目录,或仓库检出/本地开发路径。

if [ -z "$SKILL_DIR" ] || [ ! -f "$SKILL_DIR/scripts/scrape.py" ]; then for dir in "${CLAUDE_PLUGIN_ROOT:-}/skills/content-ideas" "${CLAUDE_PLUGIN_ROOT:-}" "${GEMINI_EXTENSION_DIR:-}/skills/content-ideas" "./skills/content-ideas" "."; do [ -n "$dir" ] && [ -f "$dir/scripts/scrape.py" ] && SKILL_DIR="$dir" && break done fi
echo "$SKILL_DIR"

If you can already see this file's path, just use its directory. The two
scripts you'll call are `$SKILL_DIR/scripts/scrape.py` and
`$SKILL_DIR/scripts/generate_feed.py`. The renderer template is
`$SKILL_DIR/assets/for-you-template.html` (the generator finds it automatically).
if [ -z "$SKILL_DIR" ] || [ ! -f "$SKILL_DIR/scripts/scrape.py" ]; then for dir in "${CLAUDE_PLUGIN_ROOT:-}/skills/content-ideas" "${CLAUDE_PLUGIN_ROOT:-}" "${GEMINI_EXTENSION_DIR:-}/skills/content-ideas" "./skills/content-ideas" "."; do [ -n "$dir" ] && [ -f "$dir/scripts/scrape.py" ] && SKILL_DIR="$dir" && break done fi
echo "$SKILL_DIR"

如果你已经知道本文件的路径,直接使用其所在目录即可。你需要调用的两个脚本是`$SKILL_DIR/scripts/scrape.py`和`$SKILL_DIR/scripts/generate_feed.py`。渲染模板为`$SKILL_DIR/assets/for-you-template.html`(生成器会自动找到它)。

Resolve the content home

确定内容主目录

All persistent files this skill reads and writes — the
brand/
profile and the dated
research/
runs — live under one stable base, never the current working directory. The skill runs daily and is invoked from anywhere, so the base must be the same every time or it loses the profile and the run history. Resolve it once and capture the concrete path:
bash
CONTENT_HOME="${CONTENT_HOME:-$HOME/Documents/Content}"
mkdir -p "$CONTENT_HOME/brand" "$CONTENT_HOME/research"
echo "$CONTENT_HOME"
Throughout this guide every
brand/...
and
research/...
path is relative to
$CONTENT_HOME
(so
brand/profile.md
means
$CONTENT_HOME/brand/profile.md
). Use the printed absolute path for every Read/Write of those files — the file tools don't expand shell variables, so writing a bare
brand/profile.md
would land it in the wrong directory. (Credentials stay separate, in
~/.config/content/.env
.) The scrape/generate scripts read
CONTENT_HOME
themselves, so a relative
research/{today}
passed to them resolves here too.

本技能读取和写入的所有持久化文件——
brand/
配置文件和带日期的
research/
运行记录——都存储在一个稳定的基础目录下,绝对不要使用当前工作目录。本技能每日运行且可从任意位置调用,因此基础目录必须保持一致,否则会丢失配置文件和运行历史。请一次性确认并记录具体路径:
bash
CONTENT_HOME="${CONTENT_HOME:-$HOME/Documents/Content}"
mkdir -p "$CONTENT_HOME/brand" "$CONTENT_HOME/research"
echo "$CONTENT_HOME"
本指南中所有
brand/...
research/...
路径都是相对于
$CONTENT_HOME
的(例如
brand/profile.md
指的是
$CONTENT_HOME/brand/profile.md
)。对这些文件进行读写操作时,请使用打印出的绝对路径——文件工具不会解析Shell变量,因此直接写入
brand/profile.md
会导致文件存放在错误的目录中。(凭据单独存储在
~/.config/content/.env
中。)抓取/生成脚本会自行读取
CONTENT_HOME
变量,因此传递给它们的相对路径
research/{today}
也会解析到此处。

Step 0: First-run setup

步骤0:首次运行设置

Run this before anything else, even if the user gave a topic. Detect first run by checking whether
~/.config/content/.env
exists and contains
SETUP_COMPLETE=true
. Check silently. If it's already set up, skip to Step 1.
**在进行任何操作前,请先完成此步骤,即使用户已经指定了主题。**通过检查
~/.config/content/.env
是否存在且包含
SETUP_COMPLETE=true
来判断是否为首次运行。静默检查即可。如果已完成设置,直接跳至步骤1。

0a. Welcome + API key

0a. 欢迎界面 + API密钥

Setup has three quick parts: an API key, your profile (built from your own channels), and the competitors you want to track. Only the key is required — the rest the skill bootstraps for you and you can refine any time. Nothing to install; one ScrapeCreators API key covers all four platforms — X, Instagram, TikTok, and YouTube (including transcripts).
Show this as a normal message, then call
AskUserQuestion
(don't repeat the welcome inside the modal):
I turn your social presence into a daily For You feed: I build a profile from your own channels, track the competitors you pick, and surface what's performing as content ideas backed by real engagement. I just need a ScrapeCreators API key (one key covers all four platforms; 100 free calls, no card).
AskUserQuestion
— "Add your ScrapeCreators API key?"
  • Open scrapecreators.com to grab a free key
  • I'll paste a key now
  • Skip for now
If they pick "Open scrapecreators.com", run
open https://scrapecreators.com
, then ask them to paste the key. When the user pastes a key, write
~/.config/content/.env
(create dirs; append, don't clobber other keys):
SCRAPECREATORS_API_KEY={key}
SETUP_COMPLETE=true
If they skip, write only
SETUP_COMPLETE=true
.
设置包含三个快速步骤:API密钥、你的个人配置文件(基于你自己的频道构建),以及你想要追踪的竞品。只有API密钥是必填项——其余部分技能会自动为你初始化,你可以随时进行优化。无需安装额外软件;一个ScrapeCreators API密钥即可覆盖所有四个平台——X、Instagram、TikTok和YouTube(包括字幕)。
先显示常规消息,然后调用
AskUserQuestion
(不要在弹窗内重复欢迎内容):
我可以将你的社交媒体数据转化为每日专属推荐推送:我会基于你自己的频道构建个人配置文件,追踪你选择的竞品,并将表现出色的内容转化为基于真实互动数据的内容创意。我只需要一个ScrapeCreators API密钥(一个密钥即可覆盖所有四个平台;提供100次免费调用,无需绑定银行卡)。
AskUserQuestion
— "添加你的ScrapeCreators API密钥?"
  • 打开scrapecreators.com获取免费密钥
  • 我现在粘贴密钥
  • 暂时跳过
如果用户选择“打开scrapecreators.com”,运行
open https://scrapecreators.com
,然后请用户粘贴密钥。当用户粘贴密钥后,写入
~/.config/content/.env
文件(创建必要的目录;追加内容,不要覆盖其他密钥):
SCRAPECREATORS_API_KEY={key}
SETUP_COMPLETE=true
如果用户选择跳过,只写入
SETUP_COMPLETE=true

0b. Manual alternative

0b. 手动配置替代方案

If they'd rather configure by hand, tell them to add those two lines to
~/.config/content/.env
. Offer to write the file if they paste the key here.
如果用户更倾向于手动配置,请告知他们将上述两行内容添加到
~/.config/content/.env
文件中。如果用户在此处粘贴密钥,可主动为他们写入文件。

0c. Build your brand profile

0c. 构建你的品牌配置文件

This is what personalizes everything: ideas get framed against your niche, pillars, and goal, and checked against what you've already posted. Build it from the user's own presence rather than a long questionnaire.
Ask for their own channels (
AskUserQuestion
: "Set up your profile now?" → I'll share my handles / Skip — I'll add it later). When they share handles — free-form across any platforms (
@me
on X, a YouTube channel, a TikTok, etc.) — normalize them into the
{platform: [handle]}
shape and scrape them like competitors, but over a much wider window (
--days 90
, the max) so you characterize their work from a full quarter, not just recent posts:
bash
python3 "$SKILL_DIR/scripts/scrape.py" \
  '{"x": ["me"], "youtube": ["@mychannel"]}' \
  --pillars "" --days 90
From the returned posts (plus comments/transcripts), draft the profile:
  • Niche, Audience, Voice Notes — infer from recurring topics, framing, tone.
  • Content Pillars — the 3–5 themes their posts actually cluster into. These drive
    --pillars
    on every future run, so get them right.
  • My Social Profiles — handle, follower count, bio, and a one-line content- style note per platform, taken from the scrape.
  • Target Platforms / Research Channels — the platforms they're active on.
  • Search Terms — concrete keywords from their top topics.
Two things you can't scrape — ask (
AskUserQuestion
), then fold the answers in:
  • Content Goal — why they post (lead gen / awareness / growth / thought leadership / selling…), where they drive traffic, and what they're promoting.
  • Pillar confirmation — show the 3–5 pillars you inferred and let them edit or confirm before writing.
Write
brand/profile.md
per the schema in
FILE-SCHEMAS.md
. If the scrape returned enough of their own posts, also write an initial
brand/my-content.md
(performance summary, what's working, topics covered, and audience requests distilled from their comments) — this powers anti-cannibalization and the "your audience is asking for" banner from day one.
If they skipped (or there's no API key yet to scrape with), don't block: build a minimal
brand/profile.md
from a 2–3 question Q&A (niche, rough pillars, goal), note that re-running setup with a key auto-enriches it, and move on.
这是实现个性化的核心:创意会根据你的细分领域、内容支柱和目标进行调整,并与你已发布的内容进行比对。我们会基于你自己的社交媒体数据构建配置文件,而非通过冗长的问卷。
询问用户的自有频道(
AskUserQuestion
: "现在设置你的个人配置文件?" → 我分享我的账号 / 跳过——稍后添加)。当用户分享账号时——支持任意平台的自由格式(X平台的
@me
、YouTube频道、TikTok账号等)——将其标准化为
{platform: [handle]}
格式,并像抓取竞品一样抓取这些账号,但时间范围要宽得多(
--days 90
,即最大范围),以便从完整的季度内容中分析你的创作风格,而不仅仅是近期帖子:
bash
python3 "$SKILL_DIR/scripts/scrape.py" \
  '{"x": ["me"], "youtube": ["@mychannel"]}' \
  --pillars "" --days 90
从返回的帖子(包括评论/字幕)中,起草配置文件:
  • 细分领域、受众、风格说明——从重复出现的主题、表达方式和语气中推断。
  • 内容支柱——你的帖子实际聚焦的3–5个主题。这些会驱动未来每次运行的
    --pillars
    参数,请确保准确无误。
  • 我的社交媒体配置文件——每个平台的账号、粉丝数、简介和一句内容风格说明,均来自抓取的数据。
  • 目标平台/调研渠道——你活跃的平台。
  • 搜索关键词——来自你热门主题的具体关键词。
有两项内容无法通过抓取获取——请询问用户
AskUserQuestion
),然后将答案整合到配置文件中:
  • 内容目标——你发布内容的原因(获客/品牌曝光/粉丝增长/思想领导力/销售转化……)、引流方向,以及你推广的内容。
  • 内容支柱确认——展示你推断出的3–5个内容支柱,让用户编辑或确认后再写入文件。
按照插件
FILE-SCHEMAS.md
中的 schema 写入
brand/profile.md
文件。如果抓取到足够多的用户自有帖子,还需写入初始的
brand/my-content.md
文件(表现总结、有效内容、覆盖主题,以及从评论中提炼的受众需求)——这从第一天起就可以避免内容同质化,并支持“你的受众正在询问”的提示功能。
如果用户跳过(或尚未获取API密钥无法进行抓取),不要阻塞流程:通过2–3个问题(细分领域、大致内容支柱、目标)构建一个极简的
brand/profile.md
文件,并告知用户后续使用密钥重新运行设置会自动丰富配置内容,然后继续下一步。

0d. Track competitors

0d. 追踪竞品

Ask who they want to track (
AskUserQuestion
: list them now / skip and use an example). If they list handles, create
brand/tracked-accounts/{platform}.md
files per the schema in the plugin's
FILE-SCHEMAS.md
. If they skip, run a small example so they see the shape, and tell them they can add real competitors later.
End of first-run setup. Then continue with the user's original request.

询问用户想要追踪的对象(
AskUserQuestion
: 现在列出追踪对象 / 跳过并使用示例)。如果用户列出账号,按照插件
FILE-SCHEMAS.md
中的 schema 创建
brand/tracked-accounts/{platform}.md
文件。如果用户选择跳过,运行一个小型示例让用户了解格式,并告知用户后续可以添加真实的竞品。
**首次运行设置结束。**然后继续处理用户的原始请求。

Step 1: Load context

步骤1:加载上下文

1a. Ingest the previous run's feedback into taste memory

1a. 将上一次运行的反馈整合到偏好记忆中

Before anything else, fold the last run's reactions into your memory — this is what makes each run better than the one before. List the dated subfolders of
$CONTENT_HOME/research/
(
YYYY-MM-DD
) and take the most recent one. If it has a
feedback.json
, read it and distill each entry in
reviews[]
(▲ "more like this" / ▼ "less" / a note) into the generalizable taste signal, not the one-off:
  • "▲ on three contrarian takes in the user's niche" → "gravitates toward contrarian takes"; "▼ on listicles" → "listicle formats don't land." A note often states the reason directly — use it.
  • Record these to your project memory (the auto-memory you maintain) as the user's content taste — the same place 1b recalls from. Update an existing taste note rather than duplicating it; let a single ▼ inform, not override, an established preference. Don't record one-off reactions with no pattern, anything already obvious from
    brand/profile.md
    , or post/run specifics (those live in
    research/
    ). Taste only.
If there's no prior dated folder, no
feedback.json
, or no reactions in it, skip silently. If auto-memory isn't available in this environment, skip too — the reactions stay in
feedback.json
for whenever it is. (The current run's reactions are ingested by the next run, the same way — there's no end-of-run distillation step.)
在进行任何操作前,先将上一次运行的互动记录整合到你的记忆中——这是让每次运行都比上一次更出色的关键。列出
$CONTENT_HOME/research/
目录下的带日期子文件夹(
YYYY-MM-DD
),并选取最新的一个。如果该文件夹包含
feedback.json
文件,读取并提炼
reviews[]
中的每条记录(▲“多推荐此类内容” / ▼“少推荐此类内容” / 备注),提取出可通用的偏好信号,而非单次记录:
  • “▲ 用户细分领域中的三个反向观点” → “倾向于反向观点”;“▼ 列表式内容” → “列表式内容不受欢迎”。备注通常会直接说明原因——请加以利用。
  • 将这些记录到你的项目记忆中(你维护的自动记忆),作为用户的内容偏好——与步骤1b调用的记忆位置相同。更新已有的偏好记录,而非重复添加;单次的▼记录仅作为参考,不会覆盖已确立的偏好。不要记录无规律的单次互动、
    brand/profile.md
    中已明确的内容,或帖子/运行的具体细节(这些存储在
    research/
    目录中)。仅记录偏好。
如果没有之前的带日期文件夹、没有
feedback.json
文件,或文件中没有互动记录,静默跳过即可。如果当前环境不支持自动记忆,也跳过此步骤——互动记录会保存在
feedback.json
中,待支持时再处理。(本次运行的互动记录会在下一次运行的步骤1a中被整合到偏好记忆中——无需在运行结束时进行提炼。)

1b. Recall taste and load brand context

1b. 调用偏好记忆并加载品牌上下文

Read whatever brand context exists (all optional — degrade gracefully):
  • brand/profile.md
    — niche, pillars, search terms, content goal, audience
  • brand/tracked-accounts/*.md
    — tracked creators per platform
  • brand/my-content.md
    — the user's own content performance + audience requests
Recall the user's content taste from your memory. This skill stores an evolving taste profile in your project memory (the auto-memory you maintain). Before generating ideas, recall what you know about what this user gravitates toward — preferred topics, formats, angles, creators they keep saving, and what doesn't land for them. If relevant taste signals are already surfaced in context, use them; if not and memory is available, look for taste notes tagged for this skill. This is the single most important personalization input: engagement metrics measure what audiences like, taste memory measures what this user likes. If auto-memory isn't available, fall back to engagement signals alone (and to
brand/my-content.md
if present).
If there are no tracked accounts and no topic filter, ask for handles or a topic before scraping.
读取所有已存在的品牌上下文(均为可选——优雅降级):
  • brand/profile.md
    ——细分领域、内容支柱、搜索关键词、内容目标、受众
  • brand/tracked-accounts/*.md
    ——各平台的追踪创作者
  • brand/my-content.md
    ——用户自有内容的表现 + 受众需求
从你的记忆中调用用户的内容偏好。本技能会在你的项目记忆(你维护的自动记忆)中存储一个不断进化的偏好配置文件。在生成创意前,调用你所了解的用户偏好——喜欢的主题、格式、角度、经常保存的创作者,以及不受欢迎的内容。如果相关偏好信号已在上下文中体现,直接使用;如果没有且记忆可用,查找为该技能标记的偏好记录。这是最重要的个性化输入:互动指标衡量的是受众喜欢的内容,而偏好记忆衡量的是该用户喜欢的内容。如果不支持自动记忆,仅依赖互动信号(如果存在
brand/my-content.md
也可参考)。
如果没有追踪账号且没有主题筛选条件,在抓取前请询问用户的账号或主题。

1c. Refresh your own content (
my-content.md
)

1c. 更新自有内容(
my-content.md

Before generating ideas, bring
brand/my-content.md
up to date — this is the per-run counterpart to the one-time build in Step 0c, and it's what keeps anti-cannibalization and the "your audience is asking for" banner honest as the user keeps posting. (
my-content.md
is declared updated each run in
FILE-SCHEMAS.md
; this is the step that does it.)
Take the user's own handles from the
## My Social Profiles
section of the
brand/profile.md
you just loaded, normalize them into the
{platform: [handle]}
shape, and re-scrape them over a window wide enough to catch their own cadence (
--days 30
— a creator's own posts are sparser than the merged competitor feed, but keep it "recent," not the 90-day profile build from Step 0c):
bash
python3 "$SKILL_DIR/scripts/scrape.py" \
  '{"x": ["me"], "youtube": ["@mychannel"]}' \
  --pillars "<pillars from profile.md>" --days 30
The scraper already pulls comments on the top posts, so the returned data carries the audience replies you need. Rewrite
brand/my-content.md
from it per the schema in
FILE-SCHEMAS.md
(performance summary, what's working / not, topics covered, and audience requests distilled from the comments) — it's replaced, not appended. Use this fresh version, not the copy you read in 1b, for the rest of the run.
Best-effort — never block the feed. If
profile.md
has no own handles (the user skipped profile setup), or the scrape returns nothing or errors, keep the existing
my-content.md
and continue. This refresh is an enrichment, not a gate.

在生成创意前,更新
brand/my-content.md
文件——这是步骤0c中一次性构建的对应日常运行步骤,用于确保随着用户持续发布内容,避免内容同质化和“你的受众正在询问”提示功能的准确性。(
FILE-SCHEMAS.md
中规定
my-content.md
每次运行更新;本步骤即用于完成此操作。)
从你刚刚加载的
brand/profile.md
文件的
## 我的社交媒体配置文件
部分获取用户的自有账号,将其标准化为
{platform: [handle]}
格式,并重新抓取这些账号,时间范围需足够覆盖用户的发布节奏(
--days 30
——创作者的自有帖子比整合的竞品推送更稀疏,但保持“近期”范围,而非步骤0c中用于构建配置文件的90天范围):
bash
python3 "$SKILL_DIR/scripts/scrape.py" \
  '{"x": ["me"], "youtube": ["@mychannel"]}' \
  --pillars "<来自profile.md的内容支柱>" --days 30
抓取工具会自动获取热门帖子的评论,因此返回的数据包含你需要的受众回复。按照
FILE-SCHEMAS.md
中的 schema 从返回数据中重写
brand/my-content.md
文件(表现总结、有效/无效内容、覆盖主题,以及从评论中提炼的受众需求)——替换原有内容,而非追加。在本次运行的剩余步骤中,使用这个最新版本,而非步骤1b中读取的版本。
**尽力而为——不要阻塞推送生成。**如果
profile.md
中没有自有账号(用户跳过了配置文件设置),或抓取返回空数据或出错,保留现有的
my-content.md
文件并继续运行。本更新步骤是增强功能,而非必要前置条件。

Step 2: Create the daily run folder

步骤2:创建每日运行文件夹

List existing dated subfolders of
$CONTENT_HOME/research/
(
YYYY-MM-DD
). The most recent one that is not today is the last-run date — pass it as
--since
in Step 3 so the scrape only keeps posts on/after that day. If there are no prior dated folders, there's no
--since
.
Either way, the scraper enforces a recency window so the daily feed never surfaces stale posts: by default it keeps only the last 7 days (
--days
).
--since
can only narrow that window, never widen it — so first runs and long-gap runs are both bounded to a week by default. (The script's hard cap is 90 days; for the daily feed keep it tight — a month at most. The 90-day window is for one-off profile builds in Step 0c, not the daily feed.)
Create
$CONTENT_HOME/research/{today}/
.
If
$CONTENT_HOME/research/{today}/feed-data.json
already exists
, ask whether to:
  • Refresh — re-pull and rebuild (reuse the same
    --since
    /
    --days
    )
  • Expand — widen the window: drop
    --since
    and/or raise
    --days
    (keep the feed within ~30 days) when the user wants more than the last week
  • View — just (re)open the existing feed (skip to Step 6)

列出
$CONTENT_HOME/research/
目录下已有的带日期子文件夹(
YYYY-MM-DD
)。最新的非今日日期即为上一次运行的日期——在步骤3中作为
--since
参数传递,以便抓取仅保留该日期及之后的帖子。如果没有之前的带日期文件夹,则无需设置
--since
参数。
无论哪种情况,抓取工具都会强制执行时效性窗口,确保每日推送不会显示过时内容:默认仅保留最近7天的内容(
--days
参数)。
--since
参数只能缩小该窗口,不能扩大——因此首次运行和间隔较长的运行默认都限制在一周内。(脚本的硬上限为90天;对于每日推送,请保持窗口紧凑——最多一个月。90天窗口仅用于步骤0c中的一次性配置文件构建,而非每日推送。)
创建
$CONTENT_HOME/research/{today}/
目录。
如果
$CONTENT_HOME/research/{today}/feed-data.json
已存在
,询问用户选择:
  • 刷新——重新抓取并重建(复用相同的
    --since
    /
    --days
    参数)
  • 扩展——扩大窗口范围:移除
    --since
    参数和/或增大
    --days
    参数(保持推送内容在约30天内),适用于用户想要获取超过一周内容的情况
  • 查看——仅(重新)打开现有推送(跳至步骤6)

Step 3: Scrape competitors

步骤3:抓取竞品内容

Build a JSON object mapping each platform to its tracked handles. Pass content pillars (from
brand/profile.md
, or the user's niche/topic) via
--pillars
so the script scores relevance, and the last-run date via
--since
. Leave
--days
at its default (7) unless the user asks for a wider window, then raise it (max 31).
bash
python3 "$SKILL_DIR/scripts/scrape.py" \
  '{"x": ["h1","h2"], "instagram": ["h3"], "youtube": ["@h4"]}' \
  --pillars "<the user's content pillars>" \
  --since 2026-04-15 \
  --days 7
Tell the user this takes a few minutes; progress streams to stderr. The script fetches all accounts in parallel, drops anything outside the recency window, scores engagement and relevance, flags outliers, and pulls comments/transcripts on top posts. It returns:
json
{ "results": { "x": { "h1": [ {post}, ... ] } }, "errors": [] }
Each post has
text
,
url
,
author
,
date
,
platform
,
engagement
,
score
(weighted),
relevance
(0–1 vs pillars),
baseline
(Nx the account average),
outlier
(bool), and — on top posts —
comments
/
transcript
.
On errors: report which accounts failed and proceed with what came back.
构建一个JSON对象,映射各平台与其追踪账号。通过
--pillars
参数传递内容支柱(来自
brand/profile.md
或用户的细分领域/主题),通过
--since
参数传递上一次运行的日期。保持
--days
参数为默认值(7),除非用户要求扩大窗口范围,再进行调整(最大值31)。
bash
python3 "$SKILL_DIR/scripts/scrape.py" \
  '{"x": ["h1","h2"], "instagram": ["h3"], "youtube": ["@h4"]}' \
  --pillars "<用户的内容支柱>" \
  --since 2026-04-15 \
  --days 7
告知用户此过程需要几分钟;进度会输出到stderr。脚本会并行抓取所有账号,丢弃时效性窗口外的所有内容,对互动度和相关性进行评分,标记优质内容,并获取热门帖子的评论/字幕。返回结果格式如下:
json
{ "results": { "x": { "h1": [ {post}, ... ] } }, "errors": [] }
每个帖子包含
text
url
author
date
platform
engagement
score
(加权评分)、
relevance
(与内容支柱的相关性,0–1)、
baseline
(账号平均水平的倍数)、
outlier
(布尔值),以及——对于热门帖子——
comments
/
transcript
**错误处理:**报告抓取失败的账号,然后使用返回的有效内容继续运行。

Ad-hoc: fetch specific posts by URL

临时操作:通过URL抓取特定帖子

When the user hands you specific post URLs (a competitor's viral post, a link they saw), use URL mode instead of profile mode. It returns a flat
[post]
array with the same shape:
bash
python3 "$SKILL_DIR/scripts/scrape.py" urls "https://x.com/u/status/1" "https://www.tiktok.com/@u/video/2" --pillars "..."

当用户提供特定帖子的URL(竞品的爆款帖子、用户看到的链接)时,使用URL模式而非配置文件模式。返回结果为扁平的
[post]
数组,格式与上述一致:
bash
python3 "$SKILL_DIR/scripts/scrape.py" urls "https://x.com/u/status/1" "https://www.tiktok.com/@u/video/2" --pillars "..."

Step 4: Review the scored data

步骤4:审核评分后的数据

The script pre-computes
score
,
baseline
,
relevance
, and
outlier
. Identify the top-performing posts and the topics/themes/angles driving engagement — especially high-relevance ones. This is the raw material for the Ideas tab.

脚本会预先计算
score
baseline
relevance
outlier
值。找出表现最佳的帖子,以及驱动互动的主题/话题/角度——尤其是相关性高的内容。这些是创意标签页的原始素材。

Step 5: Build the feed

步骤5:构建推送

Two tabs. Everything shown has proven engagement. Build a
FEED_DATA
object and write it (Step 6). Field-by-field structure is in the plugin's
FILE-SCHEMAS.md
(
feed-data.json
).
Tab 1 — Posts. One flat
posts[]
array merging two sources into a single sortable, filterable feed (the page handles sorting and grouping client-side — do not pre-sort or pre-group):
  • Tracked-account posts — every post from tracked accounts (no engagement gate). Set
    performance
    /
    performanceDirection
    vs the account baseline (e.g.
    "+210% vs baseline"
    ,
    "up"
    ).
  • Discovered niche outliers — statistical outliers (
    outlier: true
    , z-score 2+, or baseline 2x+). Set
    zScore
    and a
    why
    line.
    Per post, regardless of source, provide: a 1–3 sentence
    text
    summary,
    url
    ,
    handle
    +
    displayName
    (creator filter),
    platform
    , an
    engagement
    object, a hook callout when notable, and the two fields that make the feed work —
    timestamp
    (ISO 8601, drives Recent sort + relative time) and
    sortValue
    (numeric total engagement/reach, drives the default Popular sort). A post is flagged as an outlier (intensity-scaled badge + accent bar) whenever it has a
    zScore
    or
    performanceDirection: "up"
    — so a tracked post that beat its baseline shows as an outlier too.
Tab 2 — Ideas. The one place you editorialize (label it as AI suggestion). Generate up to 10 ideas, each with: a specific differentiated angle, real evidence from competitor performance, and clear differentiation from what competitors already covered.
For the generative craft — turning a topic into a differentiated angle, writing hooks, classifying funnel stage (TOFU/MOFU/BOFU), aligning CTAs, repurposing across platforms, and producing a full brief — read
references/content-strategy.md
. The short version to keep in mind while building this tab:
  • Make YOUR version, never repackage. A good angle answers at least one of: what do you know the original creator doesn't (expertise), what have you done the audience hasn't seen (access), or where do you disagree (contrarian)?
  • Anti-cannibalization. When
    brand/my-content.md
    exists, don't re-pitch a topic the user already covered unless the angle has a genuine differentiator (more depth, different format, an update, a response to feedback). Note prior coverage explicitly.
  • Own-audience demand wins. Requests from the user's own audience (
    brand/my-content.md
    ) outrank competitor signals — foreground them in the brief's "why now."
  • Taste memory biases selection. An idea that aligns with the taste signals you recalled in Step 1 (topics/formats/angles this user gravitates toward) is a stronger pick than one justified by engagement alone — and worth calling out ("this fits a pattern you keep coming back to"). Conversely, deprioritize anything that matches a recorded "doesn't land" signal.

包含两个标签页。展示的所有内容均有真实互动数据支撑。构建
FEED_DATA
对象并写入文件(步骤6)。详细字段结构请参考插件的
FILE-SCHEMAS.md
feed-data.json
)。
**标签页1 — 帖子。**一个扁平的
posts[]
数组,整合两个来源的内容,形成单一的可排序、可筛选推送(页面会在客户端处理排序和分组——不要预先排序或分组):
  • 追踪账号帖子——追踪账号的所有帖子(无互动门槛)。设置
    performance
    /
    performanceDirection
    字段,与账号平均水平对比(例如
    "+210% vs baseline"
    "up"
    )。
  • 发现的细分领域优质内容——统计意义上的优质内容(
    outlier: true
    ,z值≥2,或平均水平的2倍以上)。设置
    zScore
    why
    说明字段。
无论来源如何,每个帖子需包含:1–3句话的
text
摘要、
url
handle
+
displayName
(创作者筛选条件)、
platform
engagement
对象、值得注意的钩子标注,以及使推送正常工作的两个字段——
timestamp
(ISO 8601格式,驱动最新排序 + 相对时间显示)和
sortValue
(数字形式的总互动量/触达量,驱动默认的热门排序)。当帖子有
zScore
performanceDirection: "up"
时,会标记为优质内容(强度分级徽章 + 高亮栏)——因此表现优于平均水平的追踪账号帖子也会显示为优质内容。
**标签页2 — 创意。**这是唯一需要你进行编辑的部分(标注为AI建议)。生成最多10个创意,每个创意需包含:具体的差异化角度、来自竞品表现的真实证据,以及与竞品已有内容的明确差异化说明。
关于生成技巧——将主题转化为差异化角度、撰写钩子、分类漏斗阶段(TOFU/MOFU/BOFU)、调整CTA、跨平台复用内容,以及生成完整简报——请阅读
references/content-strategy.md
。构建本标签页时需牢记的要点:
  • **打造你的专属版本,不要简单重打包。**一个好的角度至少要回答以下问题之一:你知道哪些原创作者不知道的信息(专业知识)、你有哪些受众未曾见过的经历(独家资源),或者你在哪些方面与原观点不同(反向视角)?
  • **避免内容同质化。**当
    brand/my-content.md
    存在时,除非有真正的差异化角度(更深入、不同格式、更新内容、回应反馈),否则不要重复推荐用户已覆盖的主题。需明确标注已有内容。
  • **自有受众需求优先。**用户自有受众的需求(来自
    brand/my-content.md
    )优先级高于竞品信号——在简报的“为什么现在做”部分重点突出。
  • **偏好记忆影响选择。**与步骤1中调用的偏好信号(用户倾向的主题/格式/角度)相符的创意,比仅靠互动数据支撑的创意更优——值得特别标注(“这符合你一直关注的方向”)。反之,优先排除与记录的“不受欢迎”信号相符的创意。

Step 6: Write and open the feed

步骤6:写入并打开推送

Write the feed data to
$CONTENT_HOME/research/{today}/feed-data.json
— a JSON object with keys
meta
,
posts
,
ideas
(see
FILE-SCHEMAS.md
). Do not write HTML yourself; the generator embeds this JSON into the template.
Then render it. Default to the live server (lets the user react to items, which saves to
feedback.json
for future personalization):
bash
python3 "$SKILL_DIR/scripts/generate_feed.py" "$CONTENT_HOME/research/{today}"
This starts a local server and automatically opens the feed in the user's default browser. Still hand the user the
http://localhost:<port>
URL the command prints, so they can reopen it if the tab closes. (Pass
--no-browser
to suppress the auto-open; the URL is printed either way.) The command runs in the foreground until the user stops it with Ctrl+C, so run it in the background if you need to keep working.
In a headless/no-display environment, write a self-contained file instead and point the user at it (the page lets them download their reactions):
bash
python3 "$SKILL_DIR/scripts/generate_feed.py" "$CONTENT_HOME/research/{today}" --static
将推送数据写入
$CONTENT_HOME/research/{today}/feed-data.json
——一个包含
meta
posts
ideas
键的JSON对象(参考
FILE-SCHEMAS.md
)。 请不要自行编写HTML;生成器会将此JSON嵌入模板中。
然后渲染推送。默认使用实时服务器(允许用户与内容互动,互动记录会保存到
feedback.json
中,用于后续个性化优化):
bash
python3 "$SKILL_DIR/scripts/generate_feed.py" "$CONTENT_HOME/research/{today}"
这会启动一个本地服务器,并自动在用户的默认浏览器中打开推送。同时请告知用户命令输出的
http://localhost:<port>
URL,以便用户在标签页关闭后重新打开。(传递
--no-browser
参数可取消自动打开;无论哪种情况都会打印URL。)该命令会在前台运行,直到用户按Ctrl+C停止,因此如果需要继续工作,请在后台运行。
在无头/无显示环境中,生成独立的静态文件并告知用户文件位置(页面支持用户下载互动记录):
bash
python3 "$SKILL_DIR/scripts/generate_feed.py" "$CONTENT_HOME/research/{today}" --static

→ $CONTENT_HOME/research/{today}/for-you.html

→ $CONTENT_HOME/research/{today}/for-you.html


Then present a short text summary (post count, how many are outliers, a couple
of standout posts) and the page location.

---

然后向用户展示简短的文字摘要(帖子数量、优质内容数量、几个突出的帖子)和页面位置。

---

Step 7: Offer next steps

步骤7:提供后续操作建议

The user reacts to the feed in the browser; their reactions save to
research/{today}/feedback.json
on their own — automatically in server mode, or via the page's download button in static mode. There's no "done" signal and nothing for you to read or distill now: the file just accumulates reactions, and the next run folds them into taste memory at Step 1a. This keeps the workflow simple and, crucially, captures reactions the user makes after this conversation has ended.
Offer to: dig deeper on any idea, add/remove tracked accounts, or rerun with a different topic focus.

用户在浏览器中与推送互动;互动记录会自动保存到
research/{today}/feedback.json
中——实时服务器模式下自动保存,静态模式下用户通过页面的下载按钮保存到运行目录中。无需“完成”信号,也无需你立即读取或提炼:文件会持续积累互动记录,下一次运行时会在步骤1a中将其整合到偏好记忆中。这让工作流程保持简单,更重要的是能捕获用户在本次对话结束后做出的互动记录。
可提供以下后续操作:深入挖掘任意创意、添加/移除追踪账号,或重新运行并聚焦不同主题。

Notes

注意事项

  • Reactions / feedback → taste memory. The feed page lets the user mark items (▲ more like this / ▼ less / a note) across both tabs. In server mode these save to
    research/{date}/feedback.json
    automatically as the user clicks; in static mode the user downloads that file into the run folder. The file is just an accumulating list of reactions — no status, no submit step. The next run reads the previous run's
    feedback.json
    at Step 1a and distills it into your project memory so future runs are personalized — there is no taste file; taste lives in auto-memory.
  • No API key = no run. Both profile and URL mode require
    SCRAPECREATORS_API_KEY
    — every platform, including YouTube transcripts, goes through ScrapeCreators. If the key is missing, the script returns an error; stop and show setup instructions rather than inventing data.
  • **互动/反馈 → 偏好记忆。**推送页面允许用户标记内容(▲多推荐此类 / ▼少推荐此类 / 备注),覆盖两个标签页。实时服务器模式下,用户点击时会自动保存到
    research/{date}/feedback.json
    ;静态模式下,用户需将该文件下载到运行目录中。该文件仅为互动记录的累积列表——无状态,无提交步骤。下一次运行时会在步骤1a中读取上一次运行的
    feedback.json
    ,并提炼到你的项目记忆中,以便未来运行实现个性化——没有专门的偏好文件;偏好存储在自动记忆中。
  • **无API密钥 = 无法运行。**配置文件模式和URL模式都需要
    SCRAPECREATORS_API_KEY
    ——所有平台,包括YouTube字幕,都通过ScrapeCreators处理。如果缺少密钥,脚本会返回错误;请停止运行并展示设置说明,不要生成虚假数据。