rockcampbell.com/content/posts/claude-code-telegram-bot.md

135 lines
5.8 KiB
Markdown

---
title: "Controlling My Home Server From Telegram With Claude Code"
date: 2026-03-20
draft: false
description: "How I set up Claude Code's Telegram channel integration to manage my home server from my phone — and cleaned up some unused Docker containers while testing it out."
tags: ["Claude Code", "AI", "self-hosting", "Telegram", "homelab", "automation"]
---
I run a home server called **rocklab** — Ubuntu 24.04, a pile of Docker containers, and [Claude Code](https://claude.ai/code) acting as my on-call IT department. It handles routine maintenance, helps me publish blog posts, and executes whatever tasks I throw at it.
The one missing piece was mobility. If I wanted to check on something or kick off a task, I had to be at a terminal. That changed today when I set up **Claude Code Channels** — specifically the Telegram plugin — which lets me message my server from anywhere and have Claude respond like a proper remote assistant.
Here's how it works and how I set it up.
---
## What Are Claude Code Channels?
Channels are a research preview feature in Claude Code (v2.1.80+) that let external events push into a running Claude session. Instead of only responding when you type something at the terminal, Claude can react to messages arriving from outside — Telegram, Discord, or whatever channel plugin you've configured.
The architecture is simple:
1. You run Claude Code with `--channels plugin:telegram@claude-plugins-official`
2. A small Bun-powered MCP server listens for incoming Telegram messages
3. When a message arrives, it's injected into your Claude session
4. Claude processes it, runs whatever tools it needs, and replies back via Telegram
It's bidirectional, and it feels surprisingly natural — just like texting, except the other end of the conversation can restart your Docker containers.
---
## Prerequisites
Before setting this up, you'll need:
- **Claude Code v2.1.80+** — check with `claude --version`
- **Bun runtime** — the channel plugins are Bun scripts; install with `curl -fsSL https://bun.sh/install | bash`
- **A claude.ai login** — Channels require claude.ai authentication, not API key auth
- A Telegram account
---
## Step 1: Create a Telegram Bot
Open Telegram and start a chat with **[@BotFather](https://t.me/BotFather)**. Send `/newbot`, give it a display name and a unique username ending in `bot`. BotFather will hand you a token that looks like:
```
123456789:AAHfiqksKZ8WnHOmBabc123xyz
```
Hold onto that — it's how Claude Code authenticates with Telegram's API.
---
## Step 2: Install the Plugin and Configure the Token
In your Claude Code terminal, install the plugin:
```
/plugin install telegram@claude-plugins-official
```
Then configure it with your token:
```
/telegram:configure <your-bot-token>
```
This saves your token to `~/.claude/channels/telegram/.env`. You can also set `TELEGRAM_BOT_TOKEN` as an environment variable if you prefer.
---
## Step 3: Pair Your Telegram Account
Restart Claude Code with channels enabled:
```bash
claude --channels plugin:telegram@claude-plugins-official
```
Now DM your bot on Telegram with any message. It'll reply with a 6-character pairing code. Back in Claude Code, run:
```
/telegram:access pair <code>
```
Your Telegram user ID is now on the allowlist. To lock things down so only you can message the bot:
```
/telegram:access policy allowlist
```
Non-approved senders are silently dropped, so you don't have to worry about strangers poking at your server.
---
## What It Looks Like in Practice
Once it's running, you just... text your bot. Today I used it to:
**Check container status:**
> "Can you see what Docker containers are currently running?"
Claude ran `docker ps`, formatted the results, and sent back a clean list of all 15 containers with their uptime. Took about 5 seconds.
**Remove unused services:**
> "I'm not using any of the paperless containers, can you get rid of them?"
Claude confirmed what it was about to do, asked whether to keep the data, and once I said "get rid of everything" — took down all three paperless-ngx containers (app, postgres, redis), removed the Docker network, and cleaned up the `/home/rock/paper` directory including a root-owned subdirectory that needed a container trick to delete. Done.
That kind of task used to require SSH-ing in from my phone, navigating to the right directory, and running compose commands. Now it's a text message.
---
## A Few Things Worth Knowing
**You're still in control of permissions.** If Claude hits a tool that requires approval and you're not at the terminal, it'll wait. For fully unattended operation you can use `--dangerously-skip-permissions`, but I'd only recommend that in a trusted environment where you understand the implications.
**No message history.** The bot only sees messages as they arrive — there's no way to fetch past conversations through the API. If you need context from an earlier session, you'll have to paste it in.
**Photos work.** Send an image and Claude downloads it locally and can read it. Telegram compresses photos by default; long-press and "Send as File" if you need the original.
**It's a research preview.** The `--channels` flag syntax may change as the feature matures. Keep an eye on the Claude Code changelog.
---
## Why This Is Actually Useful
The real value isn't novelty — it's removing friction from tasks I already do. Checking on a container, verifying a service is up, cleaning out something I'm not using anymore: these are all things I'd normally do at the terminal. Now I can do them from my couch or while I'm out.
For homelab folks managing servers remotely, this is a genuinely practical addition to the toolkit. Give it a try.
---
*Rocklab runs Ubuntu 24.04 with Docker, Cloudflare Tunnels, and Claude Code as the IT department. Posts like this document how things get built and changed on this server.*