Write a post in Telegram. Publish it as a thread on Meta Threads — one tap.
Threadloom is a tiny personal Telegram bot. You send it a post; it splits the text into a proper thread (a root post plus replies, each within the 500-character Threads limit), shows you a preview, and — when you tap Publish — posts the whole thread to Meta Threads.
You in Telegram ──▶ 🧵 Threadloom bot ──▶ preview + buttons ──▶ Meta Threads
"long post" splits into a thread 📤 Publish thread is live
It has no dependencies at all — only the Python standard library — and a friendly setup wizard that walks you through every token step by step. It runs on your own computer; your tokens never leave your machine.
- ✍️ Draft in Telegram, publish to Threads. Telegram is a comfortable place to write; Threads is where the thread goes.
- ✂️ Automatic thread-splitting. Long posts become a tidy thread that respects paragraphs and sentences. No manual chopping at 500 characters.
- 📷 Photos too. Send a photo (with or without a caption) and it becomes the first post of the thread. See how photos travel below.
- 🔒 Private by design. Only your Telegram account can drive the bot.
- 🧰 Zero setup pain.
python run.pylaunches an interactive wizard that creates the bot, learns your ID automatically, and validates every token. - 🤖 Bring your own AI (optional). Want smarter splits? Plug in any OpenAI-compatible endpoint (OpenAI, OpenRouter, a local Ollama/LM Studio server) or Anthropic. Off by default — the built-in splitter needs no keys.
- Python 3.9 or newer. That's it. No
pip install, no virtual environment needed. - A Telegram account and a Threads account.
git clone https://github.com/mAia-bird/threadloom.git
cd threadloom
python run.pyThe first run launches the setup wizard. Follow it, then start the bot with
python run.py again. Open Telegram, send your bot a post, and tap
📤 Publish to Threads.
Running python run.py the first time (or python run.py setup any time) starts
an interactive guide. Here is exactly what it asks for and how to get it.
The wizard tells you to:
- Open Telegram and start a chat with @BotFather (it has a blue verified check).
- Send
/newbot. - Give the bot a display name (e.g. My Threadloom).
- Give it a username ending in
bot(e.g.my_threadloom_bot). - BotFather replies with a token like
123456789:AAExxxxx…. - Paste the token into the wizard. It checks the token with Telegram and confirms your bot's name.
So that only you can use the bot, Threadloom needs your numeric Telegram ID. You don't have to look it up — the wizard says "go message your bot", you send it any message (e.g. "hi"), and it picks up your ID for you. (If you'd rather, you can also paste it manually; @userinfobot tells you your ID.)
This is a one-time setup on Meta's developer site. The wizard summarizes it; here it is in full:
- Make sure you have a Threads account (threads.net).
- Go to developers.facebook.com and log in.
- Click Create App. When asked what you're building, choose the use case "Access the Threads API", and finish creating the app.
- Open the Threads use case in your app and add these permissions:
threads_basicthreads_content_publish
- Add yourself as a Threads tester, then accept the invite inside the Threads app (Settings → Account → Website permissions).
- Generate a user access token for your account and copy it.
- Paste the token into the wizard. It calls the Threads API to validate the token and auto-discovers your Threads user ID — so you only ever paste the token.
📎 Meta's official guide, with screenshots: https://developers.facebook.com/docs/threads/get-started
You can skip this step for now (just press Enter) and add it later — the bot still runs, it just won't publish until Threads is connected.
⏳ Tokens expire. Threads access tokens are valid for about 60 days. When yours expires, generate a fresh one and re-run
python run.py setup(or updateTHREADS_ACCESS_TOKENin.env). See long-lived tokens.
By default Threadloom splits posts itself — no keys, works offline. If you'd like an AI model to do the splitting (nicer breaks, stronger opening line), the wizard lets you plug one in:
- OpenAI-compatible — works with OpenAI, OpenRouter, Together, or a local
server like Ollama (
http://localhost:11434/v1) or LM Studio. - Anthropic — Claude models.
If the model ever fails or returns something odd, Threadloom quietly falls back to the built-in splitter, so publishing never breaks.
Start it:
python run.pyThen, in Telegram:
- Send any post as a normal message → the bot replies with a thread preview and buttons.
- Send a photo (optionally with a caption) → the photo becomes the first post; a long caption continues as text replies.
- 📤 Publish to Threads — posts the thread; you get back a link to the live thread.
- ✂️ Re-split — splits the same post again (handy after you toggle an AI model).
- ✖️ Cancel — throws the preview away.
Commands: /start, /help.
The Threads API can't accept an image file directly — it only takes a public URL that Meta's servers fetch. Handing Meta the Telegram file URL would be a security hole (that URL contains your bot token), so Threadloom does this instead:
- downloads the photo from Telegram locally,
- uploads it anonymously to Litterbox (catbox.moe's temporary host — no account, no API key),
- gives that temporary URL to Threads; Meta copies the image to its own CDN within seconds,
- the Litterbox copy self-destructs after 1 hour.
So the photo is only ever public in two places: briefly on Litterbox, and then in your published Threads post — where you were publishing it anyway. Your bot token never leaves your machine. If you'd rather not route photos through a third-party host at all, simply don't send photos — text posts never touch it.
python run.py runs in the foreground. To keep it alive after you close the
terminal, the simplest option:
nohup python run.py > threadloom.log 2>&1 &On macOS you can use a launchd agent; on Linux, a systemd --user service. Any
process manager works — it's just a normal Python program.
Everything the wizard writes lives in .env (git-ignored). You can edit it by
hand; see .env.example for the annotated template.
| Variable | What it is |
|---|---|
LANG_UI |
Interface language: en or ru. |
TELEGRAM_TOKEN |
Bot token from @BotFather. |
OWNER_ID |
Your numeric Telegram ID — the only account allowed to use the bot. |
THREADS_ACCESS_TOKEN |
Your Meta Threads access token. |
THREADS_USER_ID |
Your Threads user ID (auto-filled from the token). |
THREADS_CTA |
Optional closing post appended to every thread (≤ 500 chars), e.g. a link to your channel. |
LLM_ENABLED |
true to split with an AI model, else the built-in splitter. |
LLM_PROVIDER |
openai (any OpenAI-compatible endpoint) or anthropic. |
LLM_API_BASE |
API base URL, e.g. https://api.openai.com/v1 or http://localhost:11434/v1. |
LLM_API_KEY |
API key (leave empty for a local server that needs none). |
LLM_MODEL |
Model name, e.g. gpt-4o-mini, llama3.1, claude-haiku-4-5. |
- "Telegram rejected that token." You didn't copy the whole token, or there's a stray space. Copy it again from BotFather.
- The wizard didn't catch my ID. Make sure you messaged the right bot
(
@your_bot), then let it wait, or paste your ID from @userinfobot. - Publishing fails with a Threads API error. Usually the token expired (~60
days) or the
threads_content_publishpermission is missing. Regenerate the token and re-runpython run.py setup. - A post won't fit. Each Threads post is capped at 500 characters. Threadloom splits automatically; if a single unbroken word (like a huge URL) is longer than 500 chars, it's chopped as a last resort.
Small and readable — four moving parts, all standard library:
| File | Role |
|---|---|
threadloom/telegram_api.py |
Minimal Telegram Bot API client (long polling). |
threadloom/threads_api.py |
Publishes a thread via the Threads Graph API. |
threadloom/splitter.py |
The built-in thread splitter (paragraphs → sentences → words). |
threadloom/imagehost.py |
Anonymous 1-hour photo hosting (Litterbox) for image posts. |
threadloom/llm.py |
Optional AI splitter (OpenAI-compatible / Anthropic). |
threadloom/bot.py |
Ties it together: preview, buttons, publish. |
threadloom/setup_wizard.py |
The interactive first-run setup. |
Issues and pull requests are welcome — especially translations (the UI strings all
live in threadloom/i18n.py) and improvements to the splitter.
MIT © 2026 Maya (@mayamastra)