Skip to main content
ClaudeWave
Skill30.7k repo starsupdated today

add-telegram

This skill adds Telegram bot integration to a NanoClaw project by copying the Telegram adapter, formatting helpers, and setup utilities from the channels branch, then registering them in the main codebase. Use it when setting up a new NanoClaw instance that needs Telegram support for receiving and responding to messages through Telegram bots.

Install in Claude Code
Copy
git clone --depth 1 https://github.com/nanocoai/nanoclaw /tmp/add-telegram && cp -r /tmp/add-telegram/.claude/skills/add-telegram ~/.claude/skills/add-telegram
Then start a new Claude Code session; the skill loads automatically.

SKILL.md

# 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):

```nc:copy from-branch:channels
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:

```nc:append to:src/channels/index.ts
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:

```nc:append to:setup/index.ts at:nanoclaw:setup-steps
'pair-telegram': () => import('./pair-telegram.js'),
```

### 4. Install the adapter package

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

```nc:dep
@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.

```nc:run effect:build
pnpm run build
```
```nc:run effect:test
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 `TELEGRAM_BOT_TOKEN` can add a second bot instead of
re-pairing the first. Check which case this is; the answer steers the rest of the
flow:

```nc:run capture:has_default_bot
grep -qsE '^TELEGRAM_BOT_TOKEN=.+' .env && echo yes || echo no
```
```nc:run capture:add_another
[ "{{has_default_bot}}" = yes ] && echo ask || echo no
```

On a first install there is no bot to add another to, so `add_another` 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**):

```nc:prompt add_another validate:^(yes|no)$ normalize:lower when:add_another=ask
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**):

```nc:operator when:has_default_bot=no
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:

```nc:prompt bot_token secret validate:^[0-9]+:[A-Za-z0-9_-]{35,}$
Paste the bot token from BotFather (looks like `123456:ABC-DEF...`).
```
```nc:env-set
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:

```nc:run capture:bot_username effect:fetch
curl -sf https://api.telegram.org/bot{{bot_token}}/getMe | jq -er '.result.username'
```

### Add another bot

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

```nc:prompt bot_name validate:^[a-z0-9][a-z0-9-]*$ when:add_another=yes
Short name for the new bot
add-atomic-chat-toolSkill

Add Atomic Chat MCP server so the container agent can call local models served by the Atomic Chat desktop app via its OpenAI-compatible API.

add-codexSkill

Use 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 OneCLI. Per-group via `ncl groups config update --provider codex`. Distinct from using OpenAI as an MCP tool (where Claude remains the planner).

add-dashboardSkill

Add a monitoring dashboard to NanoClaw. Installs @nanoco/nanoclaw-dashboard and a pusher that sends periodic JSON snapshots.

add-deltachatSkill

Add DeltaChat channel integration via @deltachat/stdio-rpc-server. Native adapter — no Chat SDK bridge. Email-based messaging with end-to-end encryption.

add-discordSkill

Add Discord bot channel integration via Chat SDK.

add-emacsSkill

Add 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.

add-gcal-toolSkill

Add Google Calendar as an MCP tool (list calendars, list/search/create events, free/busy queries) using OneCLI-managed OAuth. Multi-calendar and multi-account supported. Mirrors /add-gmail-tool's stub pattern — no raw credentials ever reach the container; OneCLI injects real tokens at request time.

add-gchatSkill

Add Google Chat channel integration via Chat SDK.