Turn Claude Code into your personal assistant, accessible from anywhere via Telegram.
Send text, photos, documents, and video. See responses and tool use in real time.
I've started using Claude Code as a personal assistant, and I've built this bot so I can access it from anywhere.
Claude Code is described as an AI coding agent, but it is a capable general-purpose agent too, given the right instructions, context, and tools.
To achieve this, I set up a folder with a CLAUDE.md that teaches Claude about me (my preferences, where my notes live, my workflows), has a set of tools and scripts based on my needs, and pointed this bot at that folder.
→ See the Personal Assistant Guide for detailed setup and examples.
- Text: Ask questions, give instructions, have conversations
- Photos: Send screenshots, documents, or anything visual for analysis
- Documents: PDFs, text files, and archives (ZIP, TAR) are extracted and analyzed. A scanned PDF with no text layer is rendered to page images and read as vision input
- Video: Video messages, video notes, and videos sent as files — the audio track is transcribed and frames are pulled at scene changes, so Claude gets both the words and the picture
- Voice & audio: Voice notes and audio files are transcribed locally with whisper.cpp and answered like a typed message
- Session persistence: Conversations continue across messages
- Message queuing: Send multiple messages while Claude works — they queue up automatically. Prefix with
!or use/stopto interrupt and send immediately - Extended thinking: Say "think" for a 10k-token reasoning budget or "ultrathink" for 50k — you see the thought process as it works (configurable via
THINKING_KEYWORDSandTHINKING_DEEP_KEYWORDS) - Interactive buttons: Claude can present options as tappable inline buttons via the built-in
ask_userMCP tool - File delivery: Claude can send files (images, videos, audio, documents) back to the chat via the
send_fileMCP tool
git clone https://github.com/linuz90/claude-telegram-bot
cd claude-telegram-bot
cp .env.example .env
# Edit .env with your credentials
bun install
bun run src/index.ts- Bun 1.3+ - Install Bun. CI pins 1.3.14 and the container image ships
oven/bun:1.3-alpine - Claude Agent SDK -
@anthropic-ai/claude-agent-sdk(installed via bun install) - Telegram Bot Token from @BotFather
- ffmpeg and whisper-cli (optional, for transcription) -
brew install ffmpeg whisper-cpp. SetWHISPER_MODELto a downloaded ggml model. Without them, voice and audio messages get a reply saying transcription isn't available, videos still reach Claude with their audio marked untranscribed, and everything else is unaffected
The bot uses the @anthropic-ai/claude-agent-sdk which supports two authentication methods:
| Method | Best For | Setup |
|---|---|---|
| CLI Auth (recommended) | High usage, cost-effective | Run claude once to authenticate |
| API Key | CI/CD, environments without Claude Code | Set ANTHROPIC_API_KEY in .env |
CLI Auth (recommended): The SDK automatically uses your Claude Code login. Just ensure you've run claude at least once and authenticated. Usage bills against your Claude Code subscription, not per token.
API Key: For environments where Claude Code isn't installed. Get a key from console.anthropic.com and add to .env:
ANTHROPIC_API_KEY=sk-ant-api03-...Note: API usage is billed per token and can get expensive quickly for heavy use.
- Open @BotFather on Telegram
- Send
/newbotand follow the prompts to create your bot - Copy the token (looks like
1234567890:ABC-DEF...)
No /setcommands step needed — the bot calls setMyCommands on every boot (src/index.ts) and overwrites whatever BotFather holds. The registered set:
new - Start a new Claude session
stop - Stop the current query
status - Show session status
resume - Resume a saved session
retry - Retry the last message
restart - Restart the bot process
Create .env with your settings:
# Required
TELEGRAM_BOT_TOKEN=1234567890:ABC-DEF... # From @BotFather
TELEGRAM_ALLOWED_USERS=123456789 # Your Telegram user ID
# Recommended
CLAUDE_WORKING_DIR=/path/to/your/folder # Where Claude runs (loads CLAUDE.md, skills, MCP)Finding your Telegram user ID: Message @userinfobot on Telegram.
File access paths: By default, Claude can access:
CLAUDE_WORKING_DIR(or home directory if not set)~/Documents,~/Downloads,~/Desktop~/.claude(for Claude Code plans and settings)
To customize, set ALLOWED_PATHS in .env (comma-separated). Note: this overrides all defaults, so include ~/.claude if you want plan mode to work:
ALLOWED_PATHS=/your/project,/other/path,~/.claudeCopy and edit the MCP config:
cp mcp-config.example.ts mcp-config.ts
# Edit mcp-config.ts with your MCP serversThe bot includes two built-in MCP servers, both enabled by the copy above:
ask_user— Lets Claude present options as tappable inline keyboard buttonssend_file— Lets Claude send files (images, videos, audio, documents) back to the chat
Without a mcp-config.ts the bot runs with no MCP servers at all, so neither feature exists.
Add your own MCP servers (Things, Notion, Typefully, etc.) to give Claude access to your tools.
| Command | Description |
|---|---|
/start |
Show session status, working directory, and the command list (works, but not listed in the Telegram command menu) |
/new |
Start a fresh session |
/resume |
Pick from last 5 sessions to resume (with recap) |
/stop |
Interrupt current query |
/status |
Check what Claude is doing |
/retry |
Re-run the last message |
/restart |
Restart the bot |
cp launchagent/com.claude-telegram-ts.plist.template ~/Library/LaunchAgents/com.claude-telegram-ts.plist
# Edit the plist with your paths and env vars
launchctl load ~/Library/LaunchAgents/com.claude-telegram-ts.plistThe bot starts on login and restarts if it crashes.
Prevent sleep: To keep the bot running when your Mac is idle, go to System Settings → Battery → Options and enable "Prevent automatic sleeping when the display is off" (when on power adapter).
Logs:
tail -f /tmp/claude-telegram-bot-ts.log # stdout
tail -f /tmp/claude-telegram-bot-ts.err # stderrShell aliases: If running as a service, these aliases make it easy to manage the bot (add to ~/.zshrc or ~/.bashrc):
alias cbot='launchctl list | grep com.claude-telegram-ts'
alias cbot-stop='launchctl bootout gui/$(id -u)/com.claude-telegram-ts 2>/dev/null && echo "Stopped"'
alias cbot-start='launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.claude-telegram-ts.plist 2>/dev/null && echo "Started"'
alias cbot-restart='launchctl kickstart -k gui/$(id -u)/com.claude-telegram-ts && echo "Restarted"'
alias cbot-logs='tail -f /tmp/claude-telegram-bot-ts.log'# Run with auto-reload
bun --watch run src/index.ts
# Type check
bun run typecheck
# Or directly
bun run --bun tsc --noEmit
⚠️ Important: This bot runs Claude Code with all permission prompts bypassed. Claude can read, write, and execute commands without confirmation within the allowed paths. This is intentional for a seamless mobile experience, but you should understand the implications before deploying.
→ Read the full Security Model
Multiple layers protect against misuse:
- User allowlist - Only your Telegram IDs can use the bot
- Pre-execution tool gate - A
PreToolUseSDK hook validates every Bash/file tool call before it runs (denies underbypassPermissions), restricting file access toALLOWED_PATHSplus/tmp,/private/tmpand the process's ownTMPDIR, with a read-only exemption for~/.claude - OS Bash sandbox - Bash runs under Seatbelt (macOS) or bubblewrap (Linux), fail-closed and on by default;
BASH_SANDBOX_ENABLED=falseonly for environments that block unprivileged user namespaces - Command safety - Destructive patterns like
rm -rf /are blocked. This denylist is best-effort only — it is trivially bypassable by construction; real containment comes from the pre-execution gate, the OS sandbox, the path allowlist, and running the bot in a container - Rate limiting - Prevents runaway usage
- Audit logging - All interactions logged to
/tmp/claude-telegram-audit.log
Because the bot runs the Agent SDK with permissionMode: bypassPermissions, layers 2–4 (plus the container boundary) are the enforcing controls — not the advisory system prompt.
Bot doesn't respond
- Verify your user ID is in
TELEGRAM_ALLOWED_USERS - Check the bot token is correct
- Look at logs:
tail -f /tmp/claude-telegram-bot-ts.err - Ensure the bot process is running
Claude authentication issues
- For CLI auth: run
claudein terminal and verify you're logged in - For API key: check
ANTHROPIC_API_KEYis set and starts withsk-ant-api03- - Verify the API key has credits at console.anthropic.com
Claude can't access files
- Check
CLAUDE_WORKING_DIRpoints to an existing directory - Verify
ALLOWED_PATHSincludes directories you want Claude to access - Ensure the bot process has read/write permissions
MCP tools not working
- Verify
mcp-config.tsexists and exports properly - Check that MCP server dependencies are installed
- Look for MCP errors in the logs
MIT
