Mmcp.market

add-telegram skill

by nanocoai·nanocoai/nanoclaw·31k stars·MIT

Add Telegram channel integration via Chat SDK.

A100/100content scan

Is the add-telegram skill safe?

Clean: nothing in its files matched our rules. We read 3 files in the folder on 2026-09-28.

No findings.

Install the add-telegram skill

A skill is a folder. Copy it into your agent's skills folder and the agent loads it when the task matches its description.

git clone --depth 1 https://github.com/nanocoai/nanoclaw.git /tmp/nanoclaw
mkdir -p ~/.claude/skills
cp -r /tmp/nanoclaw/.claude/skills/add-telegram ~/.claude/skills/add-telegram
available in every project

In the Claude apps, zip the folder and upload it from the Skills settings. The folder on GitHub

The instructions your agent would load

SKILL.md as published, without the frontmatter. Read it on GitHub

Add Telegram Channel

Adds Telegram bot support via the Chat SDK bridge. NanoClaw doesn't ship channels in trunk — this skill copies the Telegram adapter, its pairing helper, and their tests in from the channels branch. The pair-telegram setup step is maintained in trunk, so it is not copied here.

The mechanical steps under Apply carry nc: directive fences: an agent reads the prose and applies them, and a parser can apply them deterministically from the same document. Every directive is idempotent, so the whole skill is safe to re-run; anything a parser can't apply falls back to the prose beside it.

Re-running with a bot already configured can add a second one instead of re-pairing the first; see Add another bot under Credentials.

Apply

1. Copy the adapter, helpers, and tests

Fetch the channels branch and copy the Telegram adapter, its pairing helper (with its test), and the focused adapter tests into place (overwrite — the branch is canonical):

src/channels/telegram.ts
src/channels/telegram-pairing.ts
src/channels/telegram-pairing.test.ts
src/channels/telegram-registration.test.ts
src/channels/telegram-connect-group.test.ts
src/channels/telegram-instances-registration.test.ts
src/channels/telegram-pairing-interceptor.test.ts

2. Register the adapter

Append the self-registration import to the channel barrel (skipped if the line is already present). This one line is the skill's only reach-in into core:

import './telegram.js';

3. Register the pairing setup step

Add the pair-telegram loader to the STEPS map in setup/index.ts, inside the dormant marker region (skipped if already present — pair-telegram ships in core, so this idempotent-skips on a normal install, but is expressed for a clean-upstream rebuild). The pairing handshake below spawns this step:

'pair-telegram': () => import('./pair-telegram.js'),

4. Install the adapter package

Pinned to an exact version — the supply-chain policy rejects ranges and latest:

@chat-adapter/telegram@4.29.0

5. Build and validate

Build first: it guards the typed createChatSdkBridge(...) core call and proves the dependency is installed. Then run the focused tests.

pnpm run build
pnpm exec vitest run src/channels/telegram-registration.test.ts src/channels/telegram-connect-group.test.ts

telegram-registration.test.ts imports the real channel barrel and asserts the registry contains telegram. It goes red if the import line is deleted or drifts, if the barrel fails to evaluate, or if @chat-adapter/telegram isn't installed (the import throws) — so it also covers the dependency from step 4. End-to-end delivery against a real bot is verified manually once the service runs.

Credentials

An install that already holds TELEGRAMBOTTOKEN can add a second bot instead of re-pairing the first. Check which case this is; the answer steers the rest of the flow:

grep -qsE '^TELEGRAM_BOT_TOKEN=.+' .env && echo yes || echo no
[ "{{has_default_bot}}" = yes ] && echo ask || echo no

On a first install there is no bot to add another to, so addanother is no and the steps below create and configure the first bot. When a bot is already configured, ask the user whether to keep using it (no: the stored token stays as it is and the flow re-pairs that bot) or to add another one (yes: the first bot's steps are satisfied by the stored token and change nothing; the new bot is handled under Add another bot**):

A Telegram bot is already configured (TELEGRAM_BOT_TOKEN in .env). Add another bot (yes), or keep using the existing one (no)?

Bot creation in Telegram is human and interactive — no parser can click through BotFather. The adapter is installed and registered, but it can't receive a message until the bot exists. On a first install, tell the user (a bot that is already configured keeps its stored token below; a second one is created under Add another bot):

Create the Telegram bot:
1. Open Telegram and message @BotFather — Telegram's official bot for creating bots.
2. Send /newbot and follow the prompts: a friendly name, then a username that must end in "bot".
3. Copy the bot token it gives you (looks like 123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11a).
4. Planning to use the bot in group chats? Send /mybots → your bot → Bot Settings → Group Privacy → Turn off, so the bot can see all messages and not just @mentions.

Collect the bot token and store it — the bridge reads it from .env (set-if-absent, so a value you've already filled in is never overwritten) and syncs it to the container:

Paste the bot token from BotFather (looks like `123456:ABC-DEF...`).
TELEGRAM_BOT_TOKEN={{bot_token}}

Confirm the token works and capture the bot's handle — getMe returns the bot account and fails here if the token is bad. You'll use the handle to open the right chat just before pairing:

curl -sf https://api.telegram.org/bot{{bot_token}}/getMe | jq -er '.result.username'

Add another bot

Only when addanother is yes. The second bot is a named adapter instance: its short name becomes the registry key telegram- and, uppercased with dashes as underscores, the token key suffix (gh-bot stores TELEGRAMBOTTOKENGHBOT). A name whose TELEGRAMBOTTOKEN key is already set is taken (storing under it would overwrite that bot's token), so it is refused:

Short name for the new bot (lowercase letters, digits, dashes; e.g. `mega`). Pick one whose token key is not already set in .env.
echo {{bot_name}} | tr 'a-z-' 'A-Z_'
! grep -qs '^TELEGRAM_BOT_TOKEN_{{bot_name_env}}=.' .env

To pair an already-configured named bot again instead (its token is stored and the service restarted, but pairing failed or was cancelled), run pnpm exec tsx setup/index.ts --step pair-telegram -- --intent main --instance telegram-, then /init-first-agent with --instance telegram- if it was never wired.

The second bot is created with @BotFather exactly like the first. Tell the user:

Create the second Telegram bot: message @BotFather, send /newbot and follow the prompts (its own friendly name, then a username that must end in "bot"), and copy the token it gives you. It must be a different bot from the one already configured. Planning to use it in group chats? Send /mybots → that bot → Bot Settings → Group Privacy → Turn off.

Then confirm its token with getMe as above:

Paste the second bot's token from BotFather (looks like `123456:ABC-DEF...`). It must belong to a different bot than the one already configured.
curl -sf https://api.telegram.org/bot{{bot_token_2}}/getMe | jq -er '.result.username'

A second token that resolves to the same bot as the first (its handle matches) is refused here, before anything is written: it would only start a second poller on that bot, which the adapter refuses at startup anyway.

[ "{{bot_username_2}}" != "{{bot_username}}" ]

Store the token under its suffixed key and list the name in TELEGRAM_INSTANCES, merged with the names already there. Both writes go through the set-env step, which updates an existing key and logs the key, never the value:

pnpm exec tsx setup/index.ts --step set-env -- --key TELEGRAM_BOT_TOKEN_{{bot_name_env}} --value {{bot_token_2}}
pnpm exec tsx setup/index.ts --step set-env -- --key TELEGRAM_INSTANCES --value "$({ sed -n 's/^TELEGRAM_INSTANCES=//p' .env; echo {{bot_name}}; } | tr ',' '\n' | grep . | sort -u | paste -sd, -)"

The registry key is how pairing and wiring address the new bot:

echo telegram-{{bot_name}}

Restart

Restart the service so it loads the Telegram adapter and the token you just stored, and wait for its CLI socket. The adapter must be live and polling before pairing — it's the thing that observes the code you send:

bash setup/lib/restart.sh

Pair your chat

Telegram tokens carry no user binding, so the agent proves you own the chat with a one-time pairing handshake: it issues a 6-digit code, you send those exact 6 digits to the bot from the chat you want to register, and the live adapter matches them. Open the bot first so you're on the right screen when the code appears. Tell the user:

Open @{{bot_username}} (https://telegram.me/{{bot_username}}) in Telegram now and keep it on screen — a 6-digit pairing code is about to appear in this terminal. When it does, send just those 6 digits to the bot as a message (in a group chat with Group Privacy on, prefix them with @{{bot_username}}). A wrong guess is rejected and a fresh code is issued automatically.

Run the pairing handshake. It prints the code, streams "waiting…" and wrong-code feedback while it watches for your message, and resolves your chat address telegram: plus your Telegram user id once the code matches:

More skills from nanocoai/nanoclaw

  • Aadd-anydocAdd local office-document-to-Markdown conversion to NanoClaw agent containers with the pinned Firecrawl AnyDoc CLI. Use when agents need to read attached Word, PowerPoint, Excel, OpenDocument, RTF, EPUB, CSV, or text-based PDF files without uploading them to a hosted parser.
  • Aadd-atomic-chat-toolAdd Atomic Chat MCP server so the container agent can call local models served by the Atomic Chat desktop app via its OpenAI-compatible API.
  • Fadd-clidashAdd clidash — a zero-dependency, read-only web dashboard that derives its tabs and tables at runtime from any CLI that lists resources as JSON. Ships pre-wired for NanoClaw's ncl CLI (agent groups, sessions, channels, users, roles), plus message-activity charts, a log tail, and a read-only file viewer for group skills/CLAUDE.md/profiles.
  • Aadd-codexUse Codex (OpenAI's codex app-server) as a full agent provider — planning, tool orchestration, MCP tools, server-side history, session resume — alongside or instead of Claude. ChatGPT subscription or OpenAI API key, vault-only via the selected gateway. Per-group via `ncl groups config update --provider codex`. Distinct from using OpenAI as an MCP tool (where Claude remains the planner).
  • Aadd-dashboardAdd a monitoring dashboard to NanoClaw. Installs @nanoco/nanoclaw-dashboard and a pusher that sends periodic JSON snapshots.
  • Aadd-deltachatAdd DeltaChat channel integration via @deltachat/stdio-rpc-server. Native adapter — no Chat SDK bridge. Email-based messaging with end-to-end encryption.
  • Cadd-dialAdd Dial channel integration — a real phone number for SMS and AI voice calls via the Dial platform (getdial.ai). Native adapter — no Chat SDK bridge.
  • Aadd-dial-numberAdd another phone number to an existing Dial channel — a second (or third) public line for the agent, so one NanoClaw install answers SMS and AI voice calls on multiple numbers. Use when Dial is already installed and the operator wants an additional number (e.g. a personal line plus a support line). Requires the Dial channel to already be installed (see /add-dial).
  • Aadd-dial-toolGive chosen NanoClaw agents a real phone number as a container tool — the `dial` CLI baked into the agent image plus OneCLI credential injection for api.getdial.ai, scoped per agent, so the agents you pick can send SMS, place AI voice calls, and receive verification codes from inside the sandbox. Independent of the Dial channel; idempotent; re-run to change which agents may use it. Use when the user wants agents to text, call, or run `dial …` from a chat, without wiring Dial as a messaging channel.
  • Aadd-discordAdd Discord bot channel integration via Chat SDK.
  • Aadd-emacsAdd Emacs as a channel. Opens an interactive chat buffer and org-mode integration so you can talk to NanoClaw from within Emacs (Doom, Spacemacs, or vanilla). Local HTTP bridge — no bot token or external service needed.
  • Aadd-gchatAdd Google Chat channel integration via Chat SDK.

All agent skills → · MCP servers