npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@antisubmissivist/clawrich

v0.2.14

Published

Telegram Bot API 10.1 Rich Message SDK for Node.js - send real tables, interactive checklists, collapsible details, math, and custom emoji. Zero-dependency, framework-agnostic. Optional OpenClaw plugin integration.

Downloads

1,865

Readme

@antisubmissivist/clawrich

Send real tables, interactive checklists, collapsible details, math, and custom emoji to Telegram 鈥?via the new Bot API 10.1 sendRichMessage method.

Pure Node.js SDK. Zero framework lock-in. Optional OpenClaw plugin integration.

npm version License: MIT Node.js


Which install is right for me?

Three install paths for three audiences 鈥?pick the one that matches you:

| You are鈥?| Install command | You get | |---|---|---| | 馃叞锔?An OpenClaw user (you already run openclaw message send) | openclaw plugins install clawhub:clawrich | A new telegram_rich_send tool your agent can call | | 馃叡锔?A Node.js developer (you want to import a library) | npm install @antisubmissivist/clawrich | A pure-Node SDK with TypeScript types | | 馃叢锔?A contributor / hacker (you want to read or fork the code) | git clone https://github.com/Antisubmissivist/clawrich.git | Full source, build, and test suite |

馃挕 Same code, three doors. The npm tarball and the ClawHub plugin share the same src/ and lib/ 鈥?the npm one is the SDK, the ClawHub one wires it as an OpenClaw tool. You don't need both.


Why

Telegram Bot API 10.1 (2026-06-11) added sendRichMessage 鈥?a new endpoint that natively renders real <table>, <checklist>, <details>, <math>, and custom emoji in any chat. No more <pre> hacks for tables, no more "list a task list of strings" 鈥?actual interactive, native Telegram elements.

clawrich wraps this in a clean, framework-agnostic Node.js SDK:

  • 鉁?Pure Node 鈥?works in any Node.js 鈮?18 project
  • 鉁?Zero dependencies (only typebox for the OpenClaw plugin shim)
  • 鉁?TypeScript-first 鈥?full type definitions included
  • 鉁?Three usage styles 鈥?SDK function call, OpenClaw plugin tool, or CLI
  • 鉁?No HTML escaping headaches 鈥?pass structured spec, get native output

Install (Node SDK)

npm install @antisubmissivist/clawrich

That's it. You now have a working sendRichMessage wrapper.


Quick start (Node SDK)

import { sendRichMessage } from 'clawrich';

const result = await sendRichMessage({
  token: process.env.TG_BOT_TOKEN,        // get from @BotFather
  chat_id: 123456789,                      // or @username
  rich_spec: {
    heading: 'Sprint Status',
    summary: 'Driver App shipped. Portal QA in progress.',
    table: {
      columns: ['Task', 'Owner', 'Status'],
      rows: [
        ['Driver App release', 'Alex', '鉁?Done'],
        ['Portal QA', 'Sam', '馃煛 In progress'],
        ['Route optimizer', 'Luke', '馃敶 Blocked']
      ]
    },
    list: [
      { text: 'Review PR', done: true },
      { text: 'Run staging smoke test', done: false },
      { text: 'Send release note', done: false }
    ],
    details: [
      {
        summary: '鈿狅笍 Risks',
        blocks: [
          'QA may slip if staging data is stale.',
          'Route optimizer dependency needs confirmation.'
        ]
      }
    ]
  }
});

console.log(result.message_id);

Or use raw HTML / Markdown

// Pass raw HTML
await sendRichMessage({
  token, chat_id,
  html: '<b>bold</b> <i>italic</i> <table>...</table>'
});

// Or raw Markdown
await sendRichMessage({
  token, chat_id,
  markdown: '**bold** _italic_ | A | B |\n|-|-|\n| 1 | 2 |'
});

Build the payload without sending

import { buildRichMessage } from 'clawrich';

const rich = buildRichMessage({
  heading: 'Title',
  table: { columns: ['A', 'B'], rows: [['1', '2']] }
});

console.log(rich.html);
// 鈫?'<h2>Title</h2>\n<table>...</table>'

CLI

# Dry-run (print payload, don't send)
node node_modules/clawrich/bin/send.js --chat_id 12345 \
  --json examples/sprint-status.json --dry-run

# Real send
node node_modules/clawrich/bin/send.js --chat_id 12345 \
  --json examples/sprint-status.json

Or install globally and use clawrich-send:

npm install -g clawrich
clawrich-send --chat_id 12345 --json sprint.json

OpenClaw plugin (optional)

If you use OpenClaw and want the same capability as a native tool, the package also exports an OpenClaw plugin:

# Install alongside OpenClaw
npm install clawrich
openclaw plugins validate clawrich   # should say "Plugin clawrich is valid"

Your agent will then be able to call the telegram_rich_send tool directly.

Note: The OpenClaw plugin shim uses typebox and openclaw/plugin-sdk as peer deps. If you don't use OpenClaw, you can ignore them 鈥?they're marked as peerDependenciesMeta.optional: true.


API reference

sendRichMessage(params)

| Field | Type | Required | Notes | |---|---|---|---| | token | string | 鉁?| Telegram bot token from @BotFather | | chat_id | string \| number | 鉁?| Numeric chat_id or @username | | rich_spec | RichMessageSpec | one of | Structured spec 鈫?auto-converted to html | | rich_message | { html?, markdown? } | one of | Pre-built Bot API payload | | html | string | one of | Raw HTML shortcut | | markdown | string | one of | Raw Markdown shortcut | | message_thread_id | number | | Forum topic thread id | | silent | boolean | | Send without notification | | is_rtl | boolean | | Right-to-left layout | | skip_entity_detection | boolean | | Skip auto-entity detection (faster) | | dry_run | boolean | | Print payload, don't send | | edit | boolean | | Edit existing message instead of sending | | message_id | string \| number | edit mode | Required when edit: true |

Returns Promise<{ ok: true, message_id, date, chat, ... }>.

RichMessageSpec (structured form)

interface RichMessageSpec {
  heading?: string;
  heading_level?: 1 | 2 | 3 | 4 | 5 | 6;  // default 2
  summary?: string;
  table?: { columns: string[]; rows: string[][] };
  list?: { text: string; done?: boolean }[];
  checklist?: { text: string; done?: boolean }[];
  details?: { summary: string; blocks: string[] }[];
  paragraphs?: string[];
  quotes?: string[];
  divider?: boolean;
}

Supported rich elements

| Element | HTML | Markdown | Notes | |---|---|---|---| | Headings (h1鈥揾6) | <h1>鈥揱|# 鈥揱###### | | | Bold | <b> | **x** | | | Italic | <i> | *x* | | | Code | <code> | `x` | | | Link | <a href> | [text](url) | | | Table | <table> / <tr> / <th> / <td> | pipe syntax | | | Checklist | <checklist> / <li has_checkbox is_checked> | [x] / [ ] | Clickable in client | | Details | <details> / <summary> | n/a | Collapsible | | Math (inline) | <math> | $x$ | | | Math (block) | <math> | $$x$$ | | | Custom emoji | custom_emoji_id | n/a | | | Divider | <hr> | --- | |

Reference: https://core.telegram.org/bots/api#rich-message-formatting-options


Environment

  • Node.js 鈮?18 (uses native fetch)
  • Telegram Bot API 鈮?10.1 (2026-06-11)
  • No transpilation, no bundler needed

Testing

git clone https://github.com/Antisubmissivist/clawrich.git
cd clawrich
npm install
npm test

Tests use Node's built-in node:test runner 鈥?no test framework dependency.


License

MIT 漏 2026 Antisubmissivist 鈥?see LICENSE


Acknowledgments