mcpField
F
felo-twitter-writer

felo-twitter-writer

github.com/felo-inc营销与增长25065 次安装14 周前更新
代码仓库

关于 felo-twitter-writer

felo-twitter-writer 是用于分析 Twitter/X 写作风格并创作推文、串文和长文的技能。它通过 Felo SuperAgent 生成内容,并可采用提取的风格 DNA 或风格库条目。

主要功能

  1. 01分析 Twitter/X 账号风格
  2. 02提取写作风格 DNA
  3. 03撰写推文和串文
  4. 04创作 X 长文
  5. 05选择风格库条目

适用场景

  1. 01分析账号的推文习惯
  2. 02依据给定风格 DNA 起草帖子
  3. 03创作多条推文串文
  4. 04撰写 X 长文

MCP 相关

该技能调用 Felo SuperAgent 生成内容;输入未说明其提供 MCP 接口。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/felo-inc/felo-skills --skill felo-twitter-writer

安装后在 Claude Code 中输入/felo-twitter-writer确认已加载。

附带文件clawhub.jsonREADME.md

详细介绍

Felo Twitter Writer 技能

限制(请先阅读)

这些规则必须遵守。违反任何一条都会导致行为错误。

  1. 此技能直接使用 SuperAgent。 所有生成均由 felo-superAgent/scripts/run_superagent.mjs 通过 --skill-id twitter-writer 处理。请勿尝试自行生成推文内容。

  2. 调用 SuperAgent 时,始终使用 --json 标志。 在 Claude Code 的 Bash 工具中,标准输出始终会被捕获,不会直接流式传输给用户。JSON 模式会以结构化响应的形式返回完整答案。脚本运行完毕后,从 JSON 输出中读取 data.answer,并将其原样打印为回复文本。

  3. 始终原样输出 data.answer。 脚本运行完毕后,将 data.answer 一字不改地打印为回复文本。请勿总结、改写,也不要在其前后添加评论。

  4. 每次调用 SuperAgent 都必须提供 --live-doc-id。 严格遵循以下规则:

    • 重用此会话中已有的任何 live_doc_id(来自之前的 SuperAgent 或 livedoc 调用)。
    • 如果没有:运行 node felo-livedoc/scripts/run_livedoc.mjs list --json,然后在 data.items 中找到第一个 is_shared === false 的条目(列表按修改时间降序排列,因此该条目是最近修改的私人 LiveDoc)。使用其 short_id。
    • 如果不存在 is_shared === false 的条目(或列表为空):运行 node felo-livedoc/scripts/run_livedoc.mjs create --name "Twitter Writer" --json,并使用 data.short_id。
    • 绝不可使用 is_shared === true 的 LiveDoc——共享 LiveDoc 属于其他项目,会导致 502 错误。
  5. 始终持久化状态。 每次调用 SuperAgent 后,从 JSON 响应字段 data.thread_short_id 和 data.live_doc_short_id 中提取 thread_short_id 和 live_doc_short_id。后续调用时使用这些值。

  6. 输出语言应与用户输入语言一致。 默认语言为 en。检测用户使用的语言,并传入对应的 --accept-language 值:日语用 ja,英语用 en,韩语用 ko,中文用 zh。如果无法确定,则使用 en。

  7. 不要向 SuperAgent 脚本传入 --timeout。 脚本会自行管理连接生命周期。

  8. 仅在模式 2 的新对话中选择品牌风格。 为内容创作开启新对话时(模式 2,没有 thread_short_id),在调用 SuperAgent 之前,必须尝试获取 TWITTER 风格库,并让用户选择风格。风格通过 --ext '{"brand_style_requirement":"..."}' 传入。完整流程见下文的“风格选择”部分。

    • 风格类别始终为 TWITTER(硬编码——此技能仅用于撰写推文)。
    • --ext 仅适用于新对话。在后续对话模式(--thread-id)中绝不要传入。
    • 如果风格库没有返回条目,则静默跳过,并在不传入 --ext 的情况下继续。
    • 模式 1(提取风格 DNA)不使用此步骤。

使用时机

当用户想要进行以下操作时,触发此技能:

  • 分析 Twitter/X 账号的写作风格
  • 从推文中提取写作风格 DNA 文档
  • 撰写、起草或创作推文 / X 帖子
  • 撰写 Twitter 线程(多条推文组成的系列)
  • 撰写 X 长文 / 长帖
  • 模仿某人的推文风格
  • 代表他人代笔撰写推文
  • 了解特定账号的写作方式

触发关键词:

  • 英语:analyze twitter style、twitter style analysis、extract writing style、style DNA、write a tweet、write tweets、draft a tweet、write a thread、twitter thread、X article、X long post、imitate tweet style、mimic tweet style、tweet in the style of、write like [account]、X account analysis、analyze X account、ghostwrite tweets、how does [account] write
  • 日语:ツイートを書く、ツイートスタイル分析、スタイルDNA、ツイートを模倣、Xアカウント分析、ツイートのスタイルを抽出、〇〇風のツイートを書く、ツイートを代筆、Xアカウントを分析、このアカウントはどう書いている

明确命令: /felo-twitter-writer、use felo twitter writer

请勿用于:

  • 仅进行一般 Twitter/X 搜索(使用 felo-x-search)
  • 一般 SuperAgent 对话(使用 felo-superAgent)
  • 网页搜索(使用 felo-search)

两种模式

模式 1 — 提取风格 DNA

适用情况: 用户提供 Twitter/X 账号名称,并希望了解或提取其写作风格。

步骤:

步骤 1:通过 felo-x-search 获取推文
node felo-x-search/scripts/run_x_search.mjs --id "USERNAME" --user --tweets --limit 30

同时获取账号资料:

node felo-x-search/scripts/run_x_search.mjs --id "USERNAME" --user
步骤 2:获取 live_doc_id

遵循上文约束 #4。

步骤 3:使用推文内容调用 SuperAgent

先确定对话模式:

  • 如果本次会话中不存在 thread_short_id → 新对话(传入 --skill-id twitter-writer)
  • 如果本次会话中已存在 thread_short_id → 后续对话(传入 --thread-id)

将 LANG 替换为用户使用的语言:en(英语)、zh(中文)、ja(日语)、ko(韩语)。参见约束 #6。

新对话(本次会话中的首次调用):

node felo-superAgent/scripts/run_superagent.mjs \
  --query "/twitter-writer ENRICHED_QUERY_WITH_TWEET_CONTENT" \
  --live-doc-id "LIVE_DOC_ID" \
  --skill-id twitter-writer \
  --accept-language LANG \
  --json

后续对话(thread_short_id 已存在):

node felo-superAgent/scripts/run_superagent.mjs \
  --query "/twitter-writer ENRICHED_QUERY_WITH_TWEET_CONTENT" \
  --thread-id "THREAD_SHORT_ID" \
  --live-doc-id "LIVE_DOC_ID" \
  --accept-language LANG \
  --json

查询构造示例:

请分析以下来自 @USERNAME 的推文,并提取一份写作风格 DNA 文档。请涵盖以下维度:语气、句子结构、开篇钩子、结尾行动号召、常用词、标签策略、表情符号用法,以及其他独特模式。

账号简介:[BIO]

推文: [TWEET_1] [TWEET_2] ...

查询内容控制在 2000 个字符以内。如果推文内容过长,请选取最具代表性的 10–15 条推文。

步骤 4:保存状态

从 JSON 响应字段 data.thread_short_id 和 data.live_doc_short_id 中提取 thread_short_id 和 live_doc_short_id。保存这些值,以便后续调用。


模式 2 — 内容创作

适用情况: 用户想要创作推文、线程或 X 长文(无论是否提供风格 DNA)。

步骤:

步骤 1:确定是否有可用的风格 DNA
  • 如果本次会话刚刚运行了模式 1 → 风格 DNA 已在 LiveDoc 画布中,使用后续对话模式
  • 如果用户直接提供风格 DNA → 将其纳入查询
  • 如果用户提供账号名称 → 先运行模式 1,然后继续模式 2
  • 如果没有风格 DNA → 进入风格库选择(步骤 1.5)
步骤 1.5:品牌风格选择(仅限新对话)

仅在以下情况下运行此步骤:

  • 这是一个新对话(会话中没有 thread_short_id),并且
  • 刚才没有运行模式 1(即不存在携带风格 DNA 上下文的现有对话)

在以下情况下完全跳过此步骤:

  • thread_short_id 已存在(后续对话)——--ext 在后续对话模式下不起作用
  • 本次会话刚才运行了模式 1——风格上下文已在对话中

1.5a. 检查用户是否已指定风格:

如果用户提到了某种风格的名称(例如,“使用我的 Bold Voice 风格”),或粘贴了风格块,记下该风格并跳到步骤 1.5d。

1.5b. 获取 TWITTER 风格库(仅名称):

重要:风格库的输出非常大(每个 Style DNA 都可能有数千个字符)。请始终使用 --json,并仅提取名称/标签,以避免 Bash 工具的输出被截断。列出风格时,绝不要在不带 --json 的情况下调用 run_style_library.mjs。

node felo-superAgent/scripts/run_style_library.mjs --category TWITTER --accept-language LANG --json | node -e "
const d=require('fs').readFileSync('/dev/stdin','utf8');
const j=JSON.parse(d);
const list=j.list||[];
const user=list.filter(s=>!s.recommended);
const rec=list.filter(s=>s.recommended);
if(user.length) { console.log('[Your styles]'); user.forEach((s,i)=>{ const labels=(s.content?.labels?.LANG||s.content?.labels?.en||[]).join(', '); console.log((i+1)+'. '+s.name+(labels?' — '+labels:'')); }); }
if(rec.length) { console.log('[Recommended styles]'); rec.forEach((s,i)=>{ const labels=(s.content?.labels?.LANG||s.content?.labels?.en||[]).join(', '); console.log((user.length+i+1)+'. '+s.name+(labels?' — '+labels:'')); }); }
if(!list.length) console.log('(No styles found)');
"

在 --accept-language 和 Node 脚本中的 labels?.LANG 引用处,都将 LANG 替换为用户的语言值(zh、ja、ko、en)。

始终传入与用户语言匹配的 --accept-language(使用与 SuperAgent 相同的值)。

1.5c. 处理结果:

如果列表为空: 静默跳过。继续执行步骤 2,不带 --ext。

如果有可用风格: 以纯文本形式输出完整列表——API 返回的每种风格都要列出,按类型分组并依次编号。绝不要使用 AskUserQuestion 工具(它最多只能提供 4 个选项,还会静默丢弃其余风格)。绝不要代替用户预选或筛选风格。始终将“无偏好”选项作为最后一项。然后等待用户以纯文本回复,再继续操作。

示例格式(根据用户的语言调整):

Here are the available Twitter writing styles — choosing one will make the output more accurate:

[Your styles]
1. My Bold Voice

[Recommended styles]
2. elonmusk — Shitposting provocateur
3. naval — Pithy aphorism master
...(list ALL styles, do not omit any)

0. No preference — use default style

1.5d. 根据所选风格构建 --ext:

用户选择风格后,使用 --json 获取该特定风格的完整 Style DNA,并在 Node.js 中提取。不要重新读取完整文本输出——Bash 工具会将其截断。

node felo-superAgent/scripts/run_style_library.mjs --category TWITTER --accept-language LANG --json | node -e "
const d=require('fs').readFileSync('/dev/stdin','utf8');
const j=JSON.parse(d);
const s=(j.list||[]).find(s=>s.name==='CHOSEN_STYLE_NAME');
if(!s){process.stderr.write('Style not found\n');process.exit(1);}
const labels=(s.content?.labels?.LANG||s.content?.labels?.en||[]).join(', ');
const dna=s.content?.styleDna||'';
const block='Style name: '+s.name+'\nStyle labels: '+labels+'\nStyle DNA: '+dna;
console.log(JSON.stringify({brand_style_requirement:block}));
"

将 CHOSEN_STYLE_NAME 替换为用户所选的风格名称,并将 LANG 替换为语言代码。

将输出的 JSON 直接作为 --ext 的值传入:

--ext "$(node felo-superAgent/scripts/run_style_library.mjs --category TWITTER --accept-language LANG --json | node -e "
const d=require('fs').readFileSync('/dev/stdin','utf8');
const j=JSON.parse(d);
const s=(j.list||[]).find(s=>s.name==='CHOSEN_STYLE_NAME');
const labels=(s.content?.labels?.LANG||s.content?.labels?.en||[]).join(', ');
const dna=s.content?.styleDna||'';
const block='Style name: '+s.name+'\nStyle labels: '+labels+'\nStyle DNA: '+dna;
console.log(JSON.stringify({brand_style_requirement:block}));
")"

如果用户选择了“无偏好”(选项 0),则不要传入 --ext。

步骤 2:获取 live_doc_id

遵循约束 #4。如果已经运行过模式 1,则复用相同的 live_doc_id。

步骤 3:确定对话模式
条件模式要传入的内容
本次会话中没有 thread_short_id(确实是首次调用)新对话--live-doc-id + --skill-id twitter-writer + --ext(如果已选择风格)
本次会话中已存在 thread_short_id(所有后续输入,包括运行模式 1 后)后续对话--thread-id + --live-doc-id(不传入 --ext)
用户说“新话题”/“重新开始”(清除 thread_short_id)新对话--live-doc-id + --skill-id twitter-writer + --ext(重复步骤 1.5)
步骤 4:调用 SuperAgent

将 LANG 替换为用户的语言:en、zh、ja、ko。请参阅约束 #6。

不带风格的新对话(没有 thread_short_id,用户选择了无偏好或列表为空):

node felo-superAgent/scripts/run_superagent.mjs \
  --query "/twitter-writer ENRICHED_QUERY" \
  --live-doc-id "LIVE_DOC_ID" \
  --skill-id twitter-writer \
  --accept-language LANG \
  --json

带品牌风格的新对话:

node felo-superAgent/scripts/run_superagent.mjs \
  --query "/twitter-writer ENRICHED_QUERY" \
  --live-doc-id "LIVE_DOC_ID" \
  --skill-id twitter-writer \
  --ext '{"brand_style_requirement":"Style name: darioamodei\nStyle labels: Thoughtful long-form essays\nStyle DNA: # Dario Amodei (@DarioAmodei) Tweet Writing Style DNA\n\n## Style Overview\nDario writes like a serious intellectual...(full content, do NOT truncate)"}' \
  --accept-language LANG \
  --json

后续对话(会话中已存在 thread_short_id):

node felo-superAgent/scripts/run_superagent.mjs \
  --query "/twitter-writer USER_FOLLOW_UP" \
  --thread-id "THREAD_SHORT_ID" \
  --live-doc-id "LIVE_DOC_ID" \
  --accept-language LANG \
  --json

查询构造指南:

  • 指明内容类型:单条推文 / 推文串 / X 长文
  • 清楚说明主题
  • 如有可用内容,加入风格 DNA 或参考账号
  • 除非用户另有指定,否则默认提供 3 个版本
  • 保留用户的核心意图;只补充背景信息并使表达更清晰

查询示例:

请以 @USERNAME 的风格(见上方风格 DNA),撰写 3 个关于 [TOPIC] 的推文版本。每个版本都应各有特色——在语气、结构或角度上有所变化。

根据上方提取的风格 DNA,撰写一组关于 [TOPIC] 的 Twitter 推文串(5–7 条推文)。开头要有一条有力的引子推文。

按照我们分析的写作风格,撰写一篇关于 [TOPIC] 的 X 长文。篇幅约为 500 个单词。

步骤 5:保存状态

从 JSON 响应字段 data.thread_short_id 和 data.live_doc_short_id 中提取 thread_short_id 和 live_doc_short_id。


模式决策逻辑

User input
  │
  ├── Contains account name + "analyze / style / DNA / how does X write"
  │   OR: アカウント名 + "分析 / スタイル / DNA / どう書いている"
  │     → Mode 1 (Style DNA Extraction) — skip style library step
  │
  ├── Contains account name + "write / create / imitate / in the style of"
  │   OR: アカウント名 + "書いて / 作って / 風に / 真似て"
  │     → Mode 1 first → then Mode 2 (follow-up, skip style library step)
  │
  ├── Contains topic + "write / draft / tweet / thread / X post"
  │   OR: トピック + "書いて / ツイート / スレッド / Xの投稿"
  │     → Mode 2 directly
  │         └── New conversation?
  │               YES → Step 1.5: fetch TWITTER styles, present to user, wait for choice
  │               NO  → follow-up, skip style library step
  │
  └── Ambiguous (e.g., "help me with tweets" / "ツイートを手伝って")
        → Ask user: do they want to analyze an account's style, or create content?

完整工作流示例

示例 A:分析账号风格
User: "Analyze @paulg's tweet style"

步骤 1: 获取推文:

node felo-x-search/scripts/run_x_search.mjs --id "paulg" --user --tweets --limit 30
node felo-x-search/scripts/run_x_search.mjs --id "paulg" --user

步骤 2: 获取 live_doc_id(列出或创建)

步骤 3: 调用 SuperAgent(模式 1——不执行风格库步骤):

node felo-superAgent/scripts/run_superagent.mjs \
  --query "/twitter-writer Please analyze the following tweets from @paulg and extract a writing style DNA document. Cover tone, sentence structure, opening hooks, closing CTAs, frequently used words, hashtag strategy, and emoji usage.\n\nAccount bio: [BIO]\n\nTweets:\n[TWEETS]" \
  --live-doc-id "LIVE_DOC_ID" \
  --skill-id twitter-writer \
  --accept-language en \
  --json

步骤 4: 从 JSON 响应字段 data.thread_short_id 和 data.live_doc_short_id 中保存 thread_short_id 和 live_doc_short_id。


示例 B:使用参考风格创作推文(模式 1 → 模式 2)
User: "Write 3 tweets about startups in @paulg's style"

步骤 1: 运行模式 1 以提取风格 DNA(与示例 A 相同)。跳过风格库步骤,因为模式 1 已在对话串中建立风格上下文。

步骤 2: 重用模式 1 中的 live_doc_id。

步骤 3: 后续调用(继续同一对话串——使用模式 1 中的 thread_short_id,不带 --ext):

node felo-superAgent/scripts/run_superagent.mjs \
  --query "/twitter-writer Based on the @paulg style DNA extracted above, write 3 tweet variations about startups. Each should have a distinct tone and angle, within 280 characters." \
  --thread-id "THREAD_SHORT_ID" \
  --live-doc-id "LIVE_DOC_ID" \
  --accept-language en \
  --json

示例 C:直接撰写推文串(模式 2,新对话,选择风格)
User: "Write a Twitter thread about why most startups fail"

步骤 1.5: 新对话,没有现有对话串 → 获取 TWITTER 风格(仅名称):

node felo-superAgent/scripts/run_style_library.mjs --category TWITTER --accept-language en --json | node -e "
const d=require('fs').readFileSync('/dev/stdin','utf8');
const j=JSON.parse(d);
const list=j.list||[];
const user=list.filter(s=>!s.recommended);
const rec=list.filter(s=>s.recommended);
if(user.length){console.log('[Your styles]');user.forEach((s,i)=>{const labels=(s.content?.labels?.en||[]).join(', ');console.log((i+1)+'. '+s.name+(labels?' — '+labels:''));});}
if(rec.length){console.log('[Recommended styles]');rec.forEach((s,i)=>{const labels=(s.content?.labels?.en||[]).join(', ');console.log((user.length+i+1)+'. '+s.name+(labels?' — '+labels:''));});}
if(!list.length)console.log('(No styles found)');
"

向用户展示:

Here are the available Twitter writing styles — choosing one will make the output more accurate:

[Your styles]
1. My Bold Voice

[Recommended styles]
2. darioamodei

0. No preference — use default style

用户回复:1

步骤 2: 获取 live_doc_id。

步骤 3: 使用选定风格开启新对话——通过 --json 提取完整的风格 DNA,并将其作为 --ext 传入:

node felo-superAgent/scripts/run_superagent.mjs \
  --query "/twitter-writer Write a Twitter thread (6–8 tweets) about why most startups fail. Start with a strong hook tweet that grabs attention. Each tweet should stand alone but flow naturally into the next." \
  --live-doc-id "LIVE_DOC_ID" \
  --skill-id twitter-writer \
  --ext "$(node felo-superAgent/scripts/run_style_library.mjs --category TWITTER --accept-language en --json | node -e "
const d=require('fs').readFileSync('/dev/stdin','utf8');
const j=JSON.parse(d);
const s=(j.list||[]).find(s=>s.name==='My Bold Voice');
const labels=(s.content?.labels?.en||[]).join(', ');
const block='Style name: '+s.name+'\nStyle labels: '+labels+'\nStyle DNA: '+s.content.styleDna;
console.log(JSON.stringify({brand_style_requirement:block}));
")" \
  --accept-language en \
  --json

步骤 4: 从 JSON 响应字段 data.thread_short_id 和 data.live_doc_short_id 中保存 thread_short_id 和 live_doc_short_id。


示例 D:迭代生成的内容(后续对话,不执行风格步骤)
User: "Make the 2nd tweet more humorous and add some emojis"

已有上次调用返回的 thread_short_id 和 live_doc_id。这是后续对话——不要再次获取风格,也不要传入 --ext。

node felo-superAgent/scripts/run_superagent.mjs \
  --query "/twitter-writer Please revise the 2nd tweet generated above. Make the tone more humorous and lighthearted, and add appropriate emojis. Keep the original intent intact." \
  --thread-id "THREAD_SHORT_ID" \
  --live-doc-id "LIVE_DOC_ID" \
  --accept-language en \
  --json

保存 JSON 响应字段 data.thread_short_id 和 data.live_doc_short_id 中更新后的 thread_short_id 和 live_doc_short_id。


示例 E:用户按名称指定风格
User: "Write a tweet about AI trends using my 'Bold Voice' style"

步骤 1.5a: 用户已经指定风格名称 → 通过 --json 提取完整的风格 DNA。无需再次询问用户。

步骤 3: 使用该风格开启新对话:

node felo-superAgent/scripts/run_superagent.mjs \
  --query "/twitter-writer Write a tweet about AI trends" \
  --live-doc-id "LIVE_DOC_ID" \
  --skill-id twitter-writer \
  --ext "$(node felo-superAgent/scripts/run_style_library.mjs --category TWITTER --accept-language en --json | node -e "
const d=require('fs').readFileSync('/dev/stdin','utf8');
const j=JSON.parse(d);
const s=(j.list||[]).find(s=>s.name==='My Bold Voice');
const labels=(s.content?.labels?.en||[]).join(', ');
const block='Style name: '+s.name+'\nStyle labels: '+labels+'\nStyle DNA: '+s.content.styleDna;
console.log(JSON.stringify({brand_style_requirement:block}));
")" \
  --accept-language en \
  --json

示例 F:风格库为空
User: "Write a tweet about the new product launch"

步骤 1.5b: 获取风格(仅名称):

node felo-superAgent/scripts/run_style_library.mjs --category TWITTER --accept-language en --json | node -e "
const d=require('fs').readFileSync('/dev/stdin','utf8');
const j=JSON.parse(d);
if(!(j.list||[]).length)console.log('(No styles found)');
else console.log((j.list||[]).map(s=>s.name).join('\n'));
"

输出:(No styles found)

静默跳过。 直接继续,不带 --ext:

node felo-superAgent/scripts/run_superagent.mjs \
  --query "/twitter-writer Write a tweet about the new product launch. Provide 3 versions with different tones." \
  --live-doc-id "LIVE_DOC_ID" \
  --skill-id twitter-writer \
  --accept-language en \
  --json

示例 G:用户选择无偏好
User: "Write a tweet about a new product launch"

步骤 1.5: 获取风格并展示列表。用户回复:0(无偏好)。

不带 --ext 继续:

node felo-superAgent/scripts/run_superagent.mjs \
  --query "/twitter-writer Write 3 tweets about a new product launch, each with a slightly different tone." \
  --live-doc-id "LIVE_DOC_ID" \
  --skill-id twitter-writer \
  --accept-language en \
  --json

错误处理

场景操作
未找到账号或未返回推文告知用户,并建议尝试其他用户名或手动提供推文示例
未设置 FELO_API_KEY停止操作并显示设置说明(与 felo-superAgent SKILL.md 相同)
SuperAgent 调用失败检查 live_doc_id 是否有效;使用相同参数重试一次
获取风格库失败将警告记录到 stderr,静默跳过,不使用 --ext 继续操作
用户要求使用模式 2,但没有风格 DNA,也没有账号继续执行步骤 1.5(选择风格库)
用户明确要求新建画布创建新的 LiveDoc:node felo-livedoc/scripts/run_livedoc.mjs create --name "Twitter Writer" --json
推文内容对于查询来说过长(超过 2000 个字符)精简到最具代表性的 10–15 条推文;优先选择互动量高的推文

参考资料

评论

支持 Markdown