SSH from a phone works, but it has friction. You need to open a terminal app, navigate to a saved host, type commands in a tiny keyboard. For emergencies it's fine. For daily server management, it gets old fast.
A better setup: a Telegram bot that talks to Claude, which talks to your server. You send a plain-English message from anywhere. Claude understands what you want, translates it to shell commands, and the bot executes and reports back. Your phone becomes a natural-language server management interface.
How the Architecture Works
The system has three layers:
- Telegram bot — your input interface. You send messages to it from any device.
- Claude API — the intelligence layer. Receives your message, decides what command to run, formats the output into plain English.
- Server agent (Node.js or Python) — runs on your VPS, receives instructions from Claude via a webhook or polling loop, executes commands, and sends results back.
The agent running on your server is the piece that actually executes shell commands. Claude never directly touches your server — it reasons about what should happen and passes instructions to the agent. This design means you can add permission gates, audit logs, and rollback logic at the agent layer.
Step-by-Step Build
Create the Telegram bot
Message @BotFather on Telegram. Use /newbot, name it, get the API token. Save it — you'll use it as TELEGRAM_BOT_TOKEN in your environment.
Get your Claude API key
Create an account at console.anthropic.com. Generate an API key. Store it as ANTHROPIC_API_KEY. We'll use claude-opus-4-6 for maximum reasoning ability.
Deploy the agent script to your server
The agent is a small Python or Node.js process that polls Telegram for messages, sends them to Claude with a system prompt describing your server, and executes the resulting commands.
Lock it down to your Telegram user ID
Get your user ID from @userinfobot. Hard-code it as an allowed sender. The bot should refuse all messages from other user IDs with no response — silence is better than an error that confirms the bot exists.
Run it as a systemd service
Create a systemd unit file so the agent starts on boot and restarts on crash. This is your always-on server management interface.
The Core Python Script
Here's a minimal working implementation. Drop this on your server and run it:
# server_agent.py — Claude + Telegram server bridge
import os, subprocess, requests, anthropic
TELEGRAM_TOKEN = os.environ["TELEGRAM_BOT_TOKEN"]
ANTHROPIC_KEY = os.environ["ANTHROPIC_API_KEY"]
ALLOWED_USER = int(os.environ["ALLOWED_USER_ID"])
client = anthropic.Anthropic(api_key=ANTHROPIC_KEY)
SYSTEM_PROMPT = """You are a server management agent for an Ubuntu 22.04 VPS.
When the user describes what they need, respond with ONLY the shell command(s) to run.
Use one command per line. Add a comment above each command explaining what it does.
Never include explanation prose — just the commands."""
def get_updates(offset=None):
params = {"timeout": 30}
if offset: params["offset"] = offset
r = requests.get(f"https://api.telegram.org/bot{TELEGRAM_TOKEN}/getUpdates", params=params)
return r.json().get("result", [])
def send_message(chat_id, text):
requests.post(f"https://api.telegram.org/bot{TELEGRAM_TOKEN}/sendMessage",
json={"chat_id": chat_id, "text": text, "parse_mode": "Markdown"})
def ask_claude(user_message):
msg = client.messages.create(
model="claude-opus-4-6",
max_tokens=1024,
system=SYSTEM_PROMPT,
messages=[{"role": "user", "content": user_message}]
)
return msg.content[0].text
def run_commands(commands_text):
output = []
for line in commands_text.strip().split("\n"):
if line.startswith("#") or not line.strip(): continue
result = subprocess.run(line, shell=True, capture_output=True, text=True, timeout=60)
output.append(f"$ {line}")
if result.stdout: output.append(result.stdout.strip())
if result.stderr: output.append(f"STDERR: {result.stderr.strip()}")
return "\n".join(output)
offset = None
print("Agent running...")
while True:
updates = get_updates(offset)
for u in updates:
offset = u["update_id"] + 1
msg = u.get("message", {})
if msg.get("from", {}).get("id") != ALLOWED_USER: continue
chat_id = msg["chat"]["id"]
text = msg.get("text", "")
if not text: continue
send_message(chat_id, "⏳ Working on it...")
commands = ask_claude(text)
result = run_commands(commands)
send_message(chat_id, f"```\n{result}\n```")
Example Conversations With Your Bot
Once the agent is running, this is what using it feels like:
You: restart nginx and check its status
Bot:
$ sudo systemctl status nginx
● nginx.service - A high performance web server
Loaded: loaded (/lib/systemd/system/nginx.service; enabled)
Active: active (running) since Fri 2025-04-11 14:32:07 UTC
You: show me the last 20 lines of the nginx error log
Bot: Returns the last 20 error log lines directly in Telegram.
You: pull the latest code for the getcodestaff site and restart pm2
Bot: Runs git pull and pm2 restart, reports back with output.
Security note: The ALLOWED_USER check is critical. Without it, anyone who finds your bot username can run arbitrary commands on your server. Also consider wrapping dangerous commands (rm, dd, chmod -R) in a confirmation prompt before executing.
Systemd Service Setup
Make the agent start automatically and restart on crashes:
[Unit]
Description=Claude Telegram Server Agent
After=network.target
[Service]
User=root
WorkingDirectory=/opt/server-agent
ExecStart=/usr/bin/python3 /opt/server-agent/server_agent.py
Restart=always
RestartSec=10
EnvironmentFile=/opt/server-agent/.env
[Install]
WantedBy=multi-user.target
# Then enable it:
systemctl daemon-reload
systemctl enable server-agent
systemctl start server-agent
Extending the Bot
The base script is just the beginning. Some extensions worth building:
- Read-only mode — accept /status, /logs, /ps commands without Claude, for quick queries that don't need AI reasoning
- Confirmation step — for destructive commands, have the bot say "I'm about to run X — reply /confirm to proceed"
- Multi-server routing — prefix commands with a server name: "prod: restart nginx" vs "staging: restart nginx"
- Scheduled commands — "remind me to check the backup job at 9am" — use a cron-like scheduler inside the agent
- Error summaries — after each command run, have Claude summarize what happened in one sentence and flag any warnings
Want a Production-Grade AI Server Agent?
We build custom AI agents that monitor infrastructure, auto-remediate issues, and report status — so you're never flying blind on your server.
Talk to the Team