Overview
Take a topic, create a Threads-optimized draft, and before publishing, review the Korean quality, and once the user approves the final version that passed the review, immediately publish it via the Graph API. There is no queue, scheduling, or state machine — within a session, it goes through one flow: create → review → approve → publish.
Publishing is something that goes out irreversibly to a public account. If Korean with spelling errors or an AI feel goes out from a business account, it stays there — that is why the review is not optional but a required step.
Scheduled and recurring publishing (e.g., "every Wednesday at 12") is handled by Claude Cowork. This skill only publishes immediately.
Trigger keywords
Threads, thread, draft, write, publish, post, posting, topic, convert
Workflow
Step 0: Apply style (if any)
Draft creation 전 check whether there is a saved style profile in:
threads_style_load(path=None)
# → {path, exists: bool, profile: <markdown or None>}
- If a profile exists (
exists: True): reflect the dimensions of the returned markdown (tone, sentence length, opening, closing, emoji, signature phrases, etc.) in the Step 1 draft creation below. The profile isthreads-style-learncreated and saved by the skill. - If no profile exists (
exists: False): if a brand tone is specified, use it; otherwise, write with a reasonable default tone (casual conversational style). Draft creation works normally even without a profile.
To create or update a profile,
threads-style-learncall the skill first.
Step 1: Analyze the topic and create a draft
Analyze the user's topic/blog post/news and create a Threads-optimized draft:
- Length limit: maximum 500 UTF-8 bytes (see the byte calculation rules below)
- Structure: short sentences, encourage conversation, 1-2 key messages
- 톤: match brand tone (if specified), default is casual conversational style
- Topic tag: optional, maximum 1 (Threads algorithm — topic tags help with exposure)
- Links: optional, maximum 5 (previews generated automatically)
Step 2: Korean review 3-stage (required before publishing)
Show the draft to the user before pass it through the ⟨Korean review 3-stage⟩. The order is fixed:
moai-coworker:ai-slop-reviewer 1차 일반 슬롭 정리
→ moai-writer:korean-spell-check 2차 맞춤법 — 제안 수집 (미공개 정보가 섞였으면 건너뜀)
→ moai-writer:korean-humanize 3차 정밀 윤문 + 맞춤법 반영 + Phase 6 최종 검수
- [HARD] Review comes before approval. If you fix sentences after approval, the text the user approved and the text that gets published differ. The user the very sentence that will be publishedmust be reviewed and approved.
- [HARD]
korean-humanizeis the last. Phase 6 final review determined meaning preservation, so the very same outputis published. There is no step to edit sentences after review. - [HARD] Genre is
카피다. SNS posts are copy, not prose.장르: 카피(mode is also auto-inferred as copy). If you apply prose standards, a normal headline rewrite will hit the change-rate gate and be halted. - [HARD] If the judgment is
hold_and_report, do not publish. Show the reason to the user as-is, and go back to step 1 and rewrite. - [HARD] After the audit, count the bytes again. Because the audit edits sentences, the byte count at the draft stage is invalid. The 500-byte judgment is based on the final version .
korean-spell-checkRegarding external transmission of: this step sends the original text to an external service (nara-speller.co.kr). Threads posts will be public anyway, so there is usually no problem. However, if the draft mixes in information not yet made public(unannounced release dates, nonpublic performance figures, contract counterparties, etc.), skip this step — even if omitted, korean-humanizechecks spelling as well.
Non-text (images and links themselves) are not subject to audit.
Step 3: Final version confirmation (approval gate)
Show the final versionthat passed the audit to the user and obtain approval. Do not publish without approval ("autonomy, not automation").
- [HARD] For approval, show the approval form to the user as-is and obtain an explicit response. Do not ask in prose, "Is this okay?" — publication is irreversible, so have the user choose explicitly.
- [HARD] Show not a summary but the exact sentences to be published. Present the full final version + final byte count + topic tags/links together, and tell the user in one line what changed in audit step 3.
- If the user requests changes, go back to step 1 and rewrite, pass audit step 3 again, and obtain re-approval.
- If the user approves, go to step 4.
Configure the options as follows:
| Options | 뜻 |
|---|---|
| Publish as-is (recommended) | Call threads_publish_text with the final version as-is |
| Request changes | Return to step 1 → pass audit step 3 again → re-approve |
| Cancel publication | Exit without publishing anything |
Step 4: Immediate publication (upon approval)
Use the threads_publish_text tool to publish the approved final version via the immediately Graph API:
threads_publish_text(text="<승인된 최종본>")
# → {media_id, container_id, permalink_hint, note}
- This skill handles text-only publication only.
- Image/video posts
threads_publish_image(text, image_url)/threads_publish_video(text, video_url)call the tool directly. [HARD] At this point, the approval screen shows not only the audited body text but also all the arguments actually being passed(media type,image_url/video_urloriginal text, publishing account)exactly as they are. If only the body text is shown for confirmation and the media URL is summarized or omitted, the user ends up approving without knowing which image will be posted. - Credentials (
THREADS_ACCESS_TOKEN,THREADS_USER_ID) If not configured,setup_requiredreturns an error — the server does not crash. For the issuance procedure, seemcp-servers/moai-mcp-threads-poster/CONNECTORS.mdreference. - [HARD] Even on failure, do not automatically retry. If the publishing tool fails ambiguously (timeout, no response), stop without retrying. The absence of a success signal is not evidence that it was not published, and retrying without confirmation posts the same content twice. Publishing is a two-step process of container creation → publishing, so retrying when only step 1 succeeded leaves a duplicate container.
- [HARD] This server has no tool to query whether something was published.
threads_get_profile은username·id·followers_count·profile_picture_urlonly returns (server.py:281) — no timeline and no post status. The other tools are only for publishing, profile, and style saving, so there is no means to ask back whether it was posted. Therefore, in the case of an ambiguous failure, ask the user to check directly in the Threads app/weband only republish after receiving the user's confirmation that it was not posted. The skill does not decide on its own.
Publishing happens immediately within the session. There is no background automatic publishing. If scheduling is needed, entrust it to Claude Cowork.
Byte calculation rules (500 UTF-8 byte limit)
The Threads text limit is not the number of characters but the number of UTF-8 bytes:
| Character type | Byte count | Example |
|---|---|---|
| ASCII (English letters, numbers, spaces, general symbols) | 1 byte | A, 1, , ? |
| Korean (가-힣) | 3 bytes | 한, 글, 🇰🇷 (excluding flag emoji) |
| Emoji (most) | 4 bytes | 😀, 🎉, 🔥 |
| Flag emoji (🇰🇷, 🇺🇸) | 8 bytes | Composed of two regional indicators |
Calculation example:
"안녕하세요!"= 5 Korean characters × 3 bytes +!1 byte = 16 bytes"Hello! 😀"= 7 ASCII characters × 1 byte + emoji 4 bytes = 11 bytes"🇰🇷 Korea"= flag 8 bytes + space 1 byte + ASCII 5 bytes = 14 bytes
Byte calculation when drafting: After writing a draft, if you ask Claude "How many bytes is this draft?", it will calculate the UTF-8 byte count for you.
Output format
After completing the 3-stage audit, submit the approval request in this format (selection is AskUserQuestion):
## 발행 최종본 (승인 요청)
<감사를 통과한 최종본 — 발행될 문장 그대로>
**바이트 수**: N / 500 ← 감사 후 다시 센 값
**토픽 태그**: (선택사항) #태그이름
**링크**: (선택사항) URL
**감사 3단 결과**: 슬롭 N건 정리 · 맞춤법 N건 반영(또는 미공개 정보로 생략) · 윤문 판정 pass
After approval, once publishing is complete:
## 발행 완료
**media_id**: ...
**permalink**: https://www.threads.net/@<username>/post/<media_id>
Precautions
| Situation | Response |
|---|---|
| When exceeding 500 bytes | Suggest reducing the draft or splitting into two posts |
| When 2 or more topic tags are requested | Recommend only 1 (Threads algorithm) |
| When 6 or more links are requested | Limit to 5 (Threads specification) |
| When image/video inclusion is requested | threads_publish_image, threads_publish_video Suggest calling the tool directly |
| When brand tone is unspecified | Suggest a casual tone draft based on industry/target, then confirm |
setup_required error |
THREADS_ACCESS_TOKEN, THREADS_USER_ID Set environment variables (see CONNECTORS.md) |
| When scheduled/regular publishing is requested | Guide them to leave it to Claude Cowork (this skill only publishes immediately) |
In the 3-stage audit, hold_and_report verdict |
Do not publish. Show the reason as-is and return to step 1 |
| Undisclosed information is mixed into the draft | korean-spell-check Omit (external transmission) — note the omission in the result |
| Exceeds 500 bytes after audit | Judge again based on the final version — suggest reducing or splitting into two posts |
| The publishing tool fails ambiguously | Do not auto-retry. Check whether it was actually published first, then decide |
| "Skip the audit and just post it" request | Do not skip. Inform them that public publishing is irreversible and proceed with the audit |
References
| File | Load condition |
|---|---|
| references/threads-spec.md | When checking Threads specifications, byte calculation, topic tags, and link limits |
Related skills
| Skill | When to use |
|---|---|
threads-style-learn |
Style analysis/save (automatically applied when this skin writes drafts) |
threads-multichannel |
Format the draft for multiple channels: Threads/Facebook/X |
moai-marketer:content-sns-content |
Brand tone guide/channel-specific optimization patterns |
moai-coworker:ai-slop-reviewer |
3-stage audit 1st — general AI slop cleanup (required before publishing) |
moai-writer:korean-spell-check |
3-stage audit 2nd — spelling/spacing (omitted if undisclosed information) |
moai-writer:korean-humanize |
3-stage audit 3rd — precise polishing + final review (장르: 카피, required before publishing, last) |
When not to use this skill
- Publishing image/video posts: MCP tool
threads_publish_image,threads_publish_videocall directly - Text formatting for Facebook/X:
threads-multichannelskill - Style analysis/save:
threads-style-learnskill - Scheduled/regular publishing: Claude Cowork (this plugin only publishes immediately)
Pre-publishing setup (first time only)
To use this skill, Threads OAuth credentials are required. First-time setup:
Do not write the token directly into .mcp.json. .mcp.jsonis a file committed to the repository, so if you put the value in as is, the token remains in the git history, diffs, and deployment packages. In this file, put only a reference (the repository's .mcp.jsonis already in this form).
{
"env": {
"THREADS_ACCESS_TOKEN": "${THREADS_ACCESS_TOKEN}",
"THREADS_USER_ID": "${THREADS_USER_ID}"
}
}
Put the actual value only in operating system environment variables. The format differs depending on the shell.
macOS / Linux (bash·zsh):
export THREADS_ACCESS_TOKEN="<장기 토큰(60일)>"
export THREADS_USER_ID="<Threads 사용자 ID>"
export THREADS_PUBLISH_DELAY="30" # 선택: 발행 전 대기 시간(초), 기본 30초
Windows (PowerShell):
$env:THREADS_ACCESS_TOKEN = "<장기 토큰(60일)>"
$env:THREADS_USER_ID = "<Threads 사용자 ID>"
$env:THREADS_PUBLISH_DELAY = "30" # 선택: 발행 전 대기 시간(초), 기본 30초
Issuance procedure: see mcp-servers/moai-mcp-threads-poster/CONNECTORS.md (browser authorization → short-lived token → long-lived token exchange)
Verify operation: threads_get_profile Call the tool → if profile information is returned, integration is successful.