Telegram newsletter
Once a day Pulse turns the archive into an issue, stores it, and sends it to a Telegram chat or channel. The same issue is readable in the dashboard and through the API.
Set up in four steps#
- Create a bot. Message @BotFather on Telegram, send
/newbot, and copy the bot token. - Choose the destination. A private chat with the bot, a group, or a channel. For a channel, add the bot as an administrator with permission to post. Use the channel handle (for example
@my_channel) or the numeric chat id. - Set the variables. Add them to
.env:TELEGRAM_BOT_TOKEN=123456:ABC... TELEGRAM_CHAT_ID=@my_channel REPORT_TIMEZONE=America/New_York # defines the local day, default UTC REPORT_HOUR=13 # local hour to send at or after, default 13 PUBLIC_URL=https://pulse.example.com # optional, adds a dashboard link - Keep Pulse running. The newsletter is a scheduled job inside the main process, so it needs
pulse startto stay up. See Deployment.
When an issue is built#
At the end of every collection cycle Pulse checks whether the current local day (in REPORT_TIMEZONE) already has an issue. If not, and the local hour is REPORT_HOUR or later, it builds one. That makes the send time resilient: if the process was down at 13:00 it sends at the first cycle after it comes back, still once per day.
Each issue covers the last 24 hours (the windowHours field) and is stored in daily_reports before anything is sent, so a failed Telegram call never loses the issue.
Preview without sending#
npm run report -- --no-send --print
npx -y -p pulse-trenches pulse report --day 2026-10-09 --no-send --print
Flags: --day YYYY-MM-DD picks the day (default today, UTC), --no-send stores the issue without sending it, --print prints the Markdown rendering. Without --no-send, the same command builds and sends on demand. You can also preview the structured data of any day with /api/reports/:day/live.
What is in an issue#
Sections appear only when they have something to say. Nothing is padded.
| Section | Contents |
|---|---|
| Market pulse | Chain-wide market cap, volume and tracked tokens. |
| Launchpads | Launches and graduations in the window, by launchpad. |
| Daily runners | Tokens with status running. |
| New and already moving | Fresh launches that already show volume. |
| Tech watch | Tokens classified as technology rather than meme, ranked by tech score. |
| Staying power | Tokens that kept showing up on discovery lists across the window. |
| Holder growth | Largest holder-count gains. |
| Volume leaders | Top 24h volume. |
| What faded | Tokens that turned dying or dead, with their peak. |
| KOL activity, Where KOLs are trading | Labelled KOL wallets and the tokens they hold. |
| Smart money, Where smart money is trading | Scored and discovered smart wallets and the tokens they hold. |
| Sectors | Volume and move by category. |
| Robinhood Chain | Launches and activity on Robinhood Chain. |
| Paid attention | Tokens that bought promotion on DexScreener (boosts and profiles). |
| Archive | Tokens and snapshots on record, plus tokens seen, snapshots, tracked trades and watched wallets in the last 24 hours. |
Optional written overview#
Set ANTHROPIC_API_KEY and each issue opens with a three to five sentence overview written by Claude (model set by ANTHROPIC_MODEL). The model receives only that day's numbers as JSON and is told never to invent a token, number or cause. If the call fails the issue goes out without it. Without a key, issues are data only, and the stored narrative is null.
Delivery details#
- Messages use Telegram HTML formatting with link previews disabled.
- Telegram caps a message at 4096 characters. Pulse splits at 3800 on section and line boundaries, repeating the section title as "(cont.)".
- Messages are sent in order with a 1.1 second pause. On a
429Pulse waits as long as Telegram asks and retries, up to four attempts per message. - The send receipt (time and message ids) is stored on the issue's
telegramcolumn, andsentin/api/reportsbecomes true. - If
PUBLIC_URLis set, the first message links toPUBLIC_URL/#/reports/<day>.
Reading issues elsewhere#
- Dashboard: the Reports page lists every stored issue and renders each one.
- API:
/api/reportsand/api/reports/:day, which includemarkdownandhtml. - MCP: the
pulse_reporttool, see MCP server.
Failures. The issue is stored before sending. If Telegram rejects a send (wrong chat id, bot not an admin), the error is logged and the day is not marked done, so Pulse retries on the next collection cycle until it goes through. Fix the variable and restart, or run pulse report yourself.