Skip to content

Instantly share code, notes, and snippets.

@devtooligan
Last active June 14, 2025 06:57
Show Gist options
  • Save devtooligan/998d1405dfa11085e4d022bb98ded85a to your computer and use it in GitHub Desktop.
Save devtooligan/998d1405dfa11085e4d022bb98ded85a to your computer and use it in GitHub Desktop.
Control with Claude code via Telegram

TELEGRAM BOT CLAUDE DAEMON INSTALLATION

A Python daemon that bridges Telegram and Claude, allowing you to interact with Claude through Telegram messages.

Overview

This bot runs as a daemon on your machine, listening for Telegram messages and executing them with Claude CLI. When you send a message to your bot on Telegram, it:

  1. Receives the message
  2. Executes it with Claude CLI
  3. Sends Claude's response back to you on Telegram

Setup

1. Create a Telegram Bot

  1. Open Telegram and find BotFather

    • Search for @BotFather in Telegram
    • Start a chat with BotFather
  2. Create a new bot

    • Send /newbot to BotFather
    • Choose a display name for your bot (e.g., "My Claude Assistant")
    • Choose a username ending in bot (e.g., myclaudeassistant_bot)
    • BotFather will give you a token like: 9866009637:AAHTj-xtpHlu6rTnzoekRAD-8l-QBGwznME
    • Save this token securely - anyone with this token can control your bot

2. Find Your Chat ID

You need your chat ID so the bot only responds to you. Choose one of these methods:

Method 1: Using a Telegram Bot (Easiest)

  1. Search for @userinfobot or @getidsbot in Telegram
  2. Start a chat with it
  3. It will immediately tell you your user ID (this is your chat_id)
  4. Your personal chat ID will be a positive number like 123456789

Method 2: Using the Debug Method

  1. Temporarily modify the telegram_daemon.py to print all chat IDs:
    async def handle_message(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
        message = update.message
        print(f"Received message from chat ID: {message.chat_id}")  # Add this line
        # ... rest of the code
  2. Run the daemon and send your bot a message
  3. Look at the console output to see your chat ID
  4. Remove the debug line once you have your ID

Method 3: Using curl (Advanced)

# Replace YOUR_BOT_TOKEN with your actual token
curl https://api.telegram.org/botYOUR_BOT_TOKEN/getUpdates

This will show recent messages to your bot in JSON format, including chat IDs.

3. Configure the Bot

  1. Edit the telegram_daemon.py file Find this line:

    chat_id = ""

    Replace it with your chat ID:

    chat_id = "123456789"  # Your actual chat ID
  2. Set the bot token Either set it as an environment variable:

    export TELEGRAM_BOT_TOKEN=9866009637:AAHTj-xtpHlu6rTnzoekRAD-8l-QBGwznME

    Or you can pass it as a command line argument when running.

Running the Bot

Basic Usage

Run with environment variable:

python telegram_daemon.py

Usage

  1. Start a conversation

    • Open Telegram
    • Find your bot by its username
    • Send /start or any message
  2. Send commands to Claude

    • Simply type any message and send it
    • The daemon will execute it with Claude and send back the response
    • Example messages:
      • "What's the weather like?"
      • "Help me write a Python function to sort a list"
      • "Explain quantum computing in simple terms"
  3. Special commands

    • Send YOLOLOG (case insensitive) to get the contents of yolo.log

Security Notes

  • The bot will ONLY respond to messages from your chat ID
  • Keep your bot token secret - don't share it or commit it to git
  • The daemon runs Claude with --dangerously-skip-permissions flag, so be mindful of what commands you send
  • Consider running the bot on a secure, private server

Troubleshooting

  • Bot not responding: Check that the daemon is running and the token is correct
  • "Chat ID not authorized": Make sure you've set the correct chat_id in the code
  • Connection errors: Ensure you have internet access and Telegram isn't blocked
  • No output: Some Claude commands might not produce output - check the daemon console for errors
  • Rate limiting: Telegram has rate limits - avoid sending too many messages too quickly

Dependencies

  • python-telegram-bot - Python wrapper for Telegram Bot API
  • asyncio - For asynchronous operations
  • subprocess - For executing Claude CLI
  • Claude CLI - Must be installed and accessible in PATH
#!/usr/bin/env python3
# : :
# : :
# : :
# ______ : :
# |______| : :
# _ | | .' :
# | `-._ | | _.-" :
# __________________|_____`._______ / /____________________________.-.____________ _.-" '.
# __.`-------------------____----------`--/`._.`-----| o| | ..__...____...-" :
# || (____) | LGB | ====================== |____________| : \_\ :
# ||_______________________________________|__________| ====================== | : .--" :
# '-._o o____(_)_____________| ============= ____..o---' `.__/ .-" _ :
# `. __0-------''-` `---..--._(|_o______.-----` `.O.` / / ," ,- .'
# ) o .' // || __//__ (_)(`,(_,'L_,_____ ____....__ _
# / ( \\ || `------` "' " """ """" .'cgmm
# / \___________//
# / __/-----------`
# _./ (
# _.-` ) ====================================================================================================================================
# \\ ( = ==== ====== ==== === === ==== == ======= ========== ===== ======== == === == =
# \\ _ o ) = ========= == ==== == ====== ===== == == ==== == ====== ========= ==== ======== ======== ==== ===== ===== =
# \\_.-` ( = ======== ==== == ==== ===== ===== ==== == ==== == ===== ======== == === ======== ======== ==== ===== ===== =
# (_____________) = ======== ==== == ==== ===== ===== ======== ==== == == === ======= ==== == ======== ======== === ===== ===== =
# = ==== ==== == ==== ===== ===== ======== ==== == === == ======= ==== == ======== ==== ======= ===== =
# = ======== ==== == ==== ===== ===== === == ==== == ==== = ======= == ======== ======== ==== ===== ===== =
# = ======== ==== == ==== ===== ===== ==== == ==== == ===== ======= ==== == ======== ======== ==== ===== ========
# = ========= == ==== == ====== ===== == == == == ====== ======= ==== == ======== ======== ==== ===== ===== =
# = ========== ====== ======= ====== ==== === ======= ======= ==== == == == ==== ===== ===== =
# ====================================================================================================================================
"""
🚨 FOOTGUN ALERT: SERIOUS SECURITY RISKS 🚨
This bot executes Claude commands DIRECTLY on your host system with NO SANDBOXING.
RISKS:
- Claude can read/write ANY file your user has access to
- Claude can execute system commands and scripts
- Claude can install software, modify configurations
- Claude can access your SSH keys, browser data, documents
- If your Telegram account is compromised, attackers get full system access
- Claude's --dangerously-skip-permissions flag bypasses all safety checks
SAFER ALTERNATIVES:
1. Use the Docker version for proper isolation
2. Run this on a dedicated VM with limited access
3. Use a restricted user account with minimal permissions
4. Never run this on a machine with sensitive data
YOU HAVE BEEN WARNED. Use at your own risk.
"""
import json
import os
import subprocess
import sys
from datetime import datetime
from pathlib import Path
from telegram import Bot, Update
from telegram.ext import (
Application,
CommandHandler,
MessageHandler,
filters,
ContextTypes,
)
# Additional runtime warning
print("=" * 60)
print("🚨 SECURITY WARNING 🚨")
print("This bot runs Claude with FULL SYSTEM ACCESS")
print("Press Ctrl+C now if you're not sure about the risks")
print("=" * 60)
class ClaudeTelegramDaemon:
def __init__(self, token: str, chat_id: str):
self.token = token
self.chat_id = chat_id
self.bot = Bot(token)
async def handle_message(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
"""
⚠️ WARNING: This executes Claude with full system access!
Handle incoming telegram messages and execute Claude commands.
"""
message = update.message
if not message or not message.text:
return
# Only respond to messages from our configured chat
if str(message.chat_id) != self.chat_id:
return
user_message = message.text
print(f"[{datetime.now()}] ⚠️ EXECUTING UNSANDBOXED: {user_message}")
# Build and execute the Claude command with streaming JSON output
cmd = [
"claude",
"--dangerously-skip-permissions", # ⚠️ THIS IS THE DANGEROUS PART
"--verbose",
"--output-format",
"stream-json",
"-p",
user_message,
]
try:
print(f"[{datetime.now()}] ⚠️ Executing Claude command...")
process = subprocess.Popen(
cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
cwd=str(Path(__file__).parent.parent),
)
results = []
error_occurred = False
# Read streaming JSON objects line by line
for line in process.stdout:
if line.strip():
try:
json_obj = json.loads(line.strip())
# Handle errors
if json_obj.get("is_error", False):
error_occurred = True
error_msg = json_obj.get("result", "Unknown error")
await message.reply_text(f"Error: {error_msg[:4000]}")
print(f"[{datetime.now()}] Error: {error_msg}")
# Handle results
elif "result" in json_obj and json_obj["result"]:
result_text = json_obj["result"]
results.append(result_text)
# Send result in chunks if needed (Telegram max is 4096 chars)
for i in range(0, len(result_text), 4096):
await message.reply_text(result_text[i : i + 4096])
except json.JSONDecodeError:
print(
f"[{datetime.now()}] Failed to parse JSON: {line.strip()}"
)
continue
process.wait()
# Handle completion
if process.returncode == 0 and not error_occurred:
if not results:
await message.reply_text(
"Command completed but no output was returned."
)
print(f"[{datetime.now()}] Claude command executed successfully")
elif process.returncode != 0:
stderr_output = process.stderr.read()
error_msg = f"Error executing Claude command:\n{stderr_output}"
print(f"[{datetime.now()}] {error_msg}")
await message.reply_text(f"Error: {stderr_output[:4000]}")
except Exception as e:
error_msg = f"Exception executing Claude: {str(e)}"
print(f"[{datetime.now()}] {error_msg}")
await message.reply_text(error_msg)
async def start_command(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
"""Handle /start command."""
await update.message.reply_text(
"CLAUDE TELEGRAM DAEMON\n\n"
"🚨 WARNING: This bot has FULL ACCESS to your system!\n"
"Claude can read files, execute commands, install software.\n\n"
"Send messages carefully. Consider using the Docker version instead.\n\n"
"Type anything to execute it with Claude..."
)
def run(self):
"""Run the telegram bot."""
print(f"Starting Telegram bot for chat ID: {self.chat_id}")
application = Application.builder().token(self.token).build()
# Add handlers
application.add_handler(CommandHandler("start", self.start_command))
application.add_handler(
MessageHandler(filters.TEXT & ~filters.COMMAND, self.handle_message)
)
# Run the bot
application.run_polling(drop_pending_updates=True)
if __name__ == "__main__":
# Get configuration from environment
token = os.environ.get("TELEGRAM_BOT_TOKEN")
if not token:
print("Error: Please set TELEGRAM_BOT_TOKEN environment variable")
sys.exit(1)
chat_id = os.environ.get("TELEGRAM_CHAT_ID", "")
if not chat_id:
print("Error: Please set TELEGRAM_CHAT_ID environment variable")
sys.exit(1)
bot = ClaudeTelegramBot(token, chat_id)
bot.run()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment