{"slug": "filaxy-herald-turn-github-activity-into-build-in-public-posts", "title": "Filaxy Herald – Turn GitHub activity into build-in-public posts", "summary": "Filaxy Herald is a new open-source tool that automatically generates build-in-public posts from GitHub activity, drafts them with AI, and sends them to Telegram for approval before posting to X. The self-hosted system runs free on Vercel and uses Claude AI to write posts, ensuring no secrets are leaked and every post is user-approved.", "body_md": "**Your GitHub work → posts on X, automatically.**\n\nFilaxy Herald watches your public repos. When you ship something, an AI writes a real\n*build-in-public* post about it, makes a branded image, and sends it to your Telegram.\nYou tap ✅ — and it's live on X. You also get an `/announce`\n\ncommand for private projects.\n\nNo \"I pushed 3 commits\" spam. Real posts. You approve every one. It runs itself.\n\n`Self-hosted`\n\n· `Runs free on Vercel`\n\n· `MIT`\n\nWhen you ship code, you get a message like this on Telegram. One tap and it's live — no dashboards, no copy-paste:\n\n**↓ It really posts.** [See a real post it published on X →](https://x.com/Othmaro_dev/status/2069607575306330549)\n\n[What it does](#what-it-does)[How it works (architecture)](#how-it-works-architecture)[Prerequisites](#prerequisites)[Setup — step by step](#setup--step-by-step)[Configuration](#configuration)[Usage](#usage)[Safety: it never posts secrets](#safety-it-never-posts-secrets)[What it costs](#what-it-costs)[Troubleshooting](#troubleshooting)[License](#license)\n\nThere are two ways posts get created:\n\n**A — Automatic (your public repos).** Once a day, Herald reads your public GitHub\nactivity. If you shipped something worth sharing (a release, a new repo, or real\ncommits to `main`\n\n), it drafts a post and sends it to you on Telegram for approval.\nIt posts **one suggestion per repo**, so you approve or discard each independently.\n\n**B — Manual ( /announce, for anything — even private projects).** Send the bot a\nmessage like\n\n`/announce my-app: shipped a live dashboard with real-time charts`\n\n. It\nwrites a polished post from your *description*(never from your code, so nothing private leaks). Attach a screenshot and it uses your real image instead of the generated card.\n\nEvery post goes through a **safety filter** (no API keys, secrets, or security bugs) and\n**you approve it on Telegram** before it ever reaches X.\n\n```\nYou ship code ─▶ GitHub\n                   │  (public activity feed — read once a day, no private repos)\n                   ▼\n            ┌──────────────┐    \"write the post\"     ┌──────────┐\n            │  The Engine  │ ──────────────────────▶ │  Claude  │\n            │   (Vercel)   │ ◀────────────────────── │    AI    │\n            └──────┬───────┘     the draft            └──────────┘\n                   │\n                   │  ① safety check (block secrets / bugs)\n                   │  ② render a branded \"ship card\" image\n                   │  ③ store the draft        ┌──────────┐\n                   │ ─────────────────────────▶│  Upstash │ (memory)\n                   ▼                            └──────────┘\n              Telegram  ──(you tap ✅ Approve)──▶  X / Twitter  ──▶  your audience grows\n```\n\n**The Engine** is a few serverless functions on Vercel. A daily**cron** triggers the digest; a**webhook** receives your Telegram button taps.- It reads your activity from GitHub's\n**public events feed**— no GitHub App, no webhook on GitHub's side, and private repos physically can't appear there. **Claude** writes the copy.**Upstash Redis** holds the pending draft between \"drafted\" and \"approved\".**Telegram** is your approval inbox.**X** is the destination.\n\n| File | What it is |\n|---|---|\n`api/digest.ts` |\nDaily cron: read activity → write → image → send to Telegram |\n`api/telegram-webhook.ts` |\nHandles your ✅/❌ taps and the `/announce` command → posts to X |\n`api/announce.ts` |\nBuilds a post from your `/announce` description |\n`lib/github.ts` |\nReads & filters your public activity |\n`lib/compose.ts` |\nPrompts Claude to write the post |\n`lib/safety.ts` |\nThe content guardrail (regex + AI review) |\n`lib/card-og.ts` |\nRenders the branded image |\n`lib/redis.ts` · `lib/telegram.ts` |\nMemory + Telegram helpers |\n\nYou'll need free accounts on these (all have free tiers; two need a few dollars of prepaid credit):\n\n| Service | Why | Cost |\n|---|---|---|\n|\n\n[Telegram](https://telegram.org)[Anthropic](https://console.anthropic.com)**$5** prepaid lasts months[X / Twitter Developer](https://developer.x.com)**~$0.02/post**[Upstash](https://upstash.com)[Vercel](https://vercel.com)Also install [Node.js 18+](https://nodejs.org) and the\n[Vercel CLI](https://vercel.com/docs/cli): `npm i -g vercel`\n\n.\n\nThen clone and install:\n\n```\ngit clone https://github.com/othmarodev/filaxy-herald.git\ncd filaxy-herald\nnpm install\ncp .env.example .env.local\n```\n\nYou'll fill `.env.local`\n\nas you go through the steps below. **It's git-ignored — your\nkeys never get committed.**\n\nThis is where you'll approve posts.\n\n- Open Telegram, search for\n**@BotFather**(the one with the blue checkmark). - Send\n`/newbot`\n\n. Give it a name, then a username ending in`bot`\n\n(e.g.`my_herald_bot`\n\n). - BotFather replies with a\n**token** like`8123456789:AAH...`\n\n. →`TELEGRAM_BOT_TOKEN`\n\n. - Now get your chat ID: search\n**@userinfobot**, press** Start**. It replies with your`Id`\n\n(a number). →`TELEGRAM_CHAT_ID`\n\n. **Open your own bot**(`t.me/your_bot_username`\n\n) and press**Start** once.*(A bot can't message you until you've messaged it first — skip this and you'll get \"chat not found\".)*\n\nTest it:\n\n```\nnpx tsx scripts/test-telegram.ts   # should send you a message\n```\n\nThis writes your posts.\n\n- Go to\n[console.anthropic.com](https://console.anthropic.com), sign in. **API Keys**→** Create Key**→ name it`filaxy-herald`\n\n. Copy the`sk-ant-...`\n\nvalue (shown once). →`ANTHROPIC_API_KEY`\n\n.**Plans & Billing**→** Buy credits**→ add**~$5**.*(The free \"evaluation\" plan has no usable credits — the key won't work until you add a little balance.)*\n\n```\nnpx tsx scripts/test-compose.ts    # generates a real sample post\n```\n\nThe fiddly one. Read carefully — there's one step that trips everyone.\n\n- Go to\n[developer.x.com](https://developer.x.com), sign in with the account you'll post from. Accept the**Free** developer plan. - You'll get a Project + an App. Open the App.\n- 🚨\n**Before generating any tokens:** open**User authentication settings → Set up**:** App permissions**→** Read and Write**.*(If you leave it on \"Read\", your tokens will be read-only and posting fails. This is THE gotcha.)***Type of App**→** Web App / Automated App or Bot**.** Callback URI**→`https://example.com/callback`\n\n(placeholder is fine).**Website URL**→ your site (anything valid).- Save.\n\n- Now go to\n**Keys and tokens** and grab**four** values:**API Key**+** API Key Secret**→`X_API_KEY`\n\n,`X_API_SECRET`\n\n**Access Token**+** Access Token Secret**(Generate) →`X_ACCESS_TOKEN`\n\n,`X_ACCESS_SECRET`\n\n. Confirm it says**Read and Write** under the token. If it says \"Read\", fix step 3 and regenerate.\n\n- The new X API is\n**pay-per-use**. Add a few dollars of credits in the developer console so it can publish.\n\n```\nnpx tsx scripts/test-x-auth.ts     # verifies the 4 keys (without posting)\n```\n\nThe bot's short-term memory (holds a draft between \"written\" and \"approved\").\n\n- Go to\n[console.upstash.com](https://console.upstash.com), create a**Redis** database (free tier, pick a region). - In the database page, find the\n**REST API** section. Copy:`UPSTASH_REDIS_REST_URL`\n\n`UPSTASH_REDIS_REST_TOKEN`\n\n```\nvercel login\nvercel link --yes          # creates the project\n```\n\nAdd your environment variables to the Vercel project (Production). Either paste them in\nthe Vercel dashboard (**Project → Settings → Environment Variables**) or via CLI:\n\n```\n# for each variable: pipe the value from .env.local so it's never printed\ngrep '^TELEGRAM_BOT_TOKEN=' .env.local | cut -d= -f2- | vercel env add TELEGRAM_BOT_TOKEN production\n# ...repeat for every var in .env.example...\n```\n\nTwo extra variables to add:\n\n```\n# stops Vercel from downloading a browser it doesn't need in the cloud\nprintf '1' | vercel env add PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD production\n# protects your cron endpoint (Vercel sends this automatically to the cron)\nprintf '%s' \"$(openssl rand -hex 16)\" | vercel env add CRON_SECRET production\n# lets the webhook call the announce endpoint internally\nprintf '%s' \"$(openssl rand -hex 16)\" | vercel env add INTERNAL_SECRET production\n```\n\nDeploy:\n\n```\nvercel --prod\n```\n\nThe daily cron is configured in `vercel.json`\n\n(`0 15 * * *`\n\n= 09:00 in UTC-6 / Costa Rica\n— change it to your timezone).\n\nSo your button taps reach the cloud. Edit the URL in `scripts/set-webhook.ts`\n\nto your\ndeployed domain, then:\n\n```\nnpx tsx scripts/set-webhook.ts\n```\n\nDone. 🎉\n\nAll in `.env.local`\n\n(and mirrored in your Vercel project). See `.env.example`\n\n.\n\n| Variable | What it is |\n|---|---|\n`TELEGRAM_BOT_TOKEN` / `TELEGRAM_CHAT_ID` |\nyour approval bot + your chat |\n`ANTHROPIC_API_KEY` |\nClaude (writes posts + runs the AI safety check) |\n`X_API_KEY` / `X_API_SECRET` / `X_ACCESS_TOKEN` / `X_ACCESS_SECRET` |\nX OAuth 1.0a (Read+Write) |\n`UPSTASH_REDIS_REST_URL` / `UPSTASH_REDIS_REST_TOKEN` |\nmemory |\n`GITHUB_USER` |\nthe GitHub username to watch |\n`ALLOWLIST` |\ncomma-separated `owner/repo` . Leave empty = all your public repos (skips your profile repo and forks). |\n`CRON_SECRET` / `INTERNAL_SECRET` |\nendpoint protection (random strings) |\n\n**Automatic:** just ship code to your public repos. Each day at your cron time, Herald DMs you a draft per repo that had activity. Tap ✅ to post, ❌ to skip.**Manual:** message your bot`/announce <project>: <what you shipped>`\n\n. Works for any project, public or private.**Attach a photo** to use a real screenshot instead of the generated card. Write in any language — the post comes out in English.\n\nEvery post — automatic or manual — runs through `lib/safety.ts`\n\nbefore it can reach\napproval:\n\n**Regex backstop**— instantly blocks anything matching an API key, token, private key, Stripe/AWS/GitHub secret, or a security-bug disclosure.**AI reviewer**— Claude flags anything sensitive the regex might miss (secrets, vulnerabilities, private data, brand-damaging content). Fails closed (blocks on doubt).\n\nAnd of course: it only ever reads your **public** GitHub feed, and `/announce`\n\nposts from\nyour **description**, never your code. Private repos can't leak.\n\n```\nnpx tsx scripts/test-safety.ts     # see the guardrail block fake secrets\n```\n\n| Item | Per post |\n|---|---|\n| X (publish) | ~$0.02 |\n| Claude (writing + safety check) | < $0.01 |\n| Branded image / screenshot | $0 |\n| Hosting (Vercel Hobby) | $0 |\nTotal |\n~2–3 cents |\n\nOne post a day ≈ **under $1/month**. A $5 X balance ≈ 250 posts. Set a spending limit in\nthe X console for peace of mind.\n\n| Symptom | Fix |\n|---|---|\nTelegram: \"chat not found\" |\nOpen your bot and press Start once (step 1.5). |\nAnthropic: \"credit balance too low\" |\nAdd ~$5 in Plans & Billing — the free plan has no credits. |\nX: tokens are read-only / posting 403 |\nSet Read and Write in User auth settings, then regenerate the access token. |\nX: \"CreditsDepleted\" |\nAdd credits in the X developer console (pay-per-use). |\nWebhook returns 500 / ERR_MODULE_NOT_FOUND |\nVercel Node functions need self-contained imports — keep `api/telegram-webhook.ts` dependency-light (it is, by design). |\nCron runs but nothing posts |\nThat's correct if you had no post-worthy public activity that day — it never invents posts. |\nThe `/announce` post links the wrong place |\nPrivate projects link to your GitHub profile by design (never the private repo). |\n\n[MIT](/othmarodev/filaxy-herald/blob/main/LICENSE) © Othmaro Fallas Rojas — [@Othmaro_dev](https://x.com/Othmaro_dev) ·\n[github.com/othmarodev](https://github.com/othmarodev)\n\nBuilt in public. This bot announces its own updates. 🤖", "url": "https://wpnews.pro/news/filaxy-herald-turn-github-activity-into-build-in-public-posts", "canonical_source": "https://github.com/othmarodev/filaxy-herald", "published_at": "2026-06-24 18:23:19+00:00", "updated_at": "2026-06-24 18:40:25.119936+00:00", "lang": "en", "topics": ["developer-tools", "generative-ai", "ai-tools"], "entities": ["Filaxy Herald", "GitHub", "Telegram", "X", "Vercel", "Claude", "Upstash", "Anthropic"], "alternates": {"html": "https://wpnews.pro/news/filaxy-herald-turn-github-activity-into-build-in-public-posts", "markdown": "https://wpnews.pro/news/filaxy-herald-turn-github-activity-into-build-in-public-posts.md", "text": "https://wpnews.pro/news/filaxy-herald-turn-github-activity-into-build-in-public-posts.txt", "jsonld": "https://wpnews.pro/news/filaxy-herald-turn-github-activity-into-build-in-public-posts.jsonld"}}