关于 felo-twitter-writer
felo-twitter-writer 是用于分析 Twitter/X 写作风格并创作推文、串文和长文的技能。它通过 Felo SuperAgent 生成内容,并可采用提取的风格 DNA 或风格库条目。
主要功能
- 01分析 Twitter/X 账号风格
- 02提取写作风格 DNA
- 03撰写推文和串文
- 04创作 X 长文
- 05选择风格库条目
适用场景
- 01分析账号的推文习惯
- 02依据给定风格 DNA 起草帖子
- 03创作多条推文串文
- 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 技能
限制(请先阅读)
这些规则必须遵守。违反任何一条都会导致行为错误。
-
此技能直接使用 SuperAgent。 所有生成均由
felo-superAgent/scripts/run_superagent.mjs通过--skill-id twitter-writer处理。请勿尝试自行生成推文内容。 -
调用 SuperAgent 时,始终使用
--json标志。 在 Claude Code 的 Bash 工具中,标准输出始终会被捕获,不会直接流式传输给用户。JSON 模式会以结构化响应的形式返回完整答案。脚本运行完毕后,从 JSON 输出中读取data.answer,并将其原样打印为回复文本。 -
始终原样输出
data.answer。 脚本运行完毕后,将data.answer一字不改地打印为回复文本。请勿总结、改写,也不要在其前后添加评论。 -
每次调用 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 错误。
- 重用此会话中已有的任何
-
始终持久化状态。 每次调用 SuperAgent 后,从 JSON 响应字段
data.thread_short_id和data.live_doc_short_id中提取thread_short_id和live_doc_short_id。后续调用时使用这些值。 -
输出语言应与用户输入语言一致。 默认语言为
en。检测用户使用的语言,并传入对应的--accept-language值:日语用ja,英语用en,韩语用ko,中文用zh。如果无法确定,则使用en。 -
不要向 SuperAgent 脚本传入
--timeout。 脚本会自行管理连接生命周期。 -
仅在模式 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 条推文;优先选择互动量高的推文 |
参考资料
- felo-superAgent SKILL.md — SuperAgent 调用约定、
--ext格式和风格库脚本 - felo-x-search SKILL.md — X/Twitter 搜索命令
- felo-livedoc SKILL.md — LiveDoc 管理命令
- Felo Open Platform
- 获取 API 密钥(Settings → API Keys)