Claudio is an adapter for Claude Code CLI and Telegram. It makes a tunnel between a private network and Telegram's API. So that users can chat with Claude Code remotely, in a safe way.
+---------------------------------------------+
| Remote Machine |
| |
| |
+----------+ | +---------+ +-----------------+ |
| Telegram |<--------+--->| Claudio |<----->| Claude Code CLI | |
+----------+ | +---------+ +-----------------+ |
+---------------------------------------------+
Claudio starts a local HTTP server that listens on port 8421, and creates a tunnel using cloudflared. When the user sends a message from Telegram, it's sent to <cloudflare-tunnel-url>/telegram/webhook and forwarded to the Claude Code CLI.
The user message is passed as a one-shot prompt, along with some context to maintain continuity. The last 100 messages are kept by default (configurable via MAX_HISTORY_LINES).
After Claude Code finishes, it outputs the response in plain text to stdout for Claudio to capture it and forward it to Telegram API.
The whole purpose of Claudio is to give you remote access to Claude Code from your Telegram app — without breaking Anthropic's Terms of Service. This means Claude Code runs with full permissions by design:
--dangerously-skip-permissions, --permission-mode bypassPermissions, AND --disable-slash-commands
When running as root, IS_SANDBOX=1 is required for Claude Code to start. Claudio sets this automatically when it detects root. For non-root users, this variable is optional.
These flags are intentional. Since there's no human in front of the terminal to approve permission prompts, Claude Code must run autonomously. Claudio mitigates the risk through: webhook secret validation (HMAC), single authorized chat_id, and binding the HTTP server to localhost only (external access goes through cloudflared).
- Claude Code CLI (with Pro/Max subscription)
- Linux/macOS/WSL
- Telegram bot token
- Homebrew (macOS only, for installing dependencies)
python3,curlsqlite3,jq,cloudflared(auto-installed if missing)
- Clone the repository and run the install command:
git clone https://github.com/edgarjs/claudio.git
cd claudio
./claudio installThis will:
- Install dependencies (
sqlite3,jq,cloudflared) if not already present - Create a symlink at
~/.local/bin/claudioso you can runclaudiofrom anywhere - Set up a Cloudflare named tunnel (permanent URL, requires a free Cloudflare account)
- Install a systemd/launchd service
Note: If
~/.local/binis not in your PATH, you'll need to add it. See the installation output for instructions.
- Set up Telegram bot
In Telegram, message @BotFather with /newbot and follow instructions to create a bot. At the end, you'll be given a secret token, copy it and then run:
claudio telegram setupPaste your Telegram token when asked, and press Enter. Then, send a /start message to your bot from the Telegram account that you'll use to communicate with Claude Code.
The setup wizard will confirm when it receives the message and finish. Once done, the service restarts automatically, and you can start chatting with Claude Code.
For security, only the
chat_idcaptured during setup is authorized to send messages.
A cron job runs every minute to verify the webhook is registered and re-registers it if needed. If the server is unreachable, the health check auto-restarts the service (throttled to once per 3 minutes, max 3 attempts). After 3 restart attempts without recovery, it sends a Telegram alert and stops retrying until the service recovers. State files:
$HOME/.claudio/.last_restart_attempt(throttle),$HOME/.claudio/.restart_fail_count(attempt counter) — delete these to reset.
Check the service and webhook status:
claudio statusTo update Claudio to the latest stable release:
claudio updateTo view recent logs (default 50 lines):
claudio logFollow logs in real time with -f, or change the line count with -n:
claudio log -f
claudio log -n 100To stop and remove the service run:
claudio uninstallIf you want to remove the $HOME/.claudio directory completely, run:
claudio uninstall --purgeClaudio uses Haiku by default. If you want to switch to another model, just send the name of the model as a command: /opus, /sonnet, or /haiku. And then continue chatting.
Claudio supports voice messages in both directions using ElevenLabs. Set ELEVENLABS_API_KEY in your service.env to enable voice features (ELEVENLABS_VOICE_ID defaults to Chris if not set). When you send a voice message, Claudio transcribes it (STT), processes it, and responds with a voice message (as a reply) followed by a text version for reference. Text messages always get text-only responses. If ELEVENLABS_API_KEY is not set, voice messages will be rejected with an error reply.
You can send photos or image files directly to Claudio. Include an optional caption to tell Claude what to do with the image, or send it without a caption and Claude will describe it.
- Supported formats: JPEG, PNG, GIF, WebP
- Sending as photo: Telegram compresses images automatically
- Sending as document: Attach an image file for lossless quality
- Size limit: 20 MB (Telegram bot API constraint)
Images are validated (magic byte verification, size check) and stored temporarily during processing, then deleted immediately after Claude responds.
You can send documents (PDF, text files, CSV, code files, etc.) to Claudio. Include an optional caption to tell Claude what to do with the file, or send it without a caption and Claude will read and summarize it.
- Any file type supported by Telegram's document upload (files with image MIME types are routed through the image pipeline instead)
- Size limit: 20 MB (Telegram bot API constraint)
- Claude reads the file directly from disk — text-based formats (PDF, CSV, code, plain text) work best; binary files may produce limited results
- Files are stored temporarily during processing, then deleted immediately after Claude responds
Claudio appends a system prompt that defines its persona, core principles, and communication style (optimized for chat). The default is generated on first run at $HOME/.claudio/SYSTEM_PROMPT.md. You can customize it by editing that file — it's read at runtime so no need to restart.
Claudio stores its configuration and other files in $HOME/.claudio/. Settings are managed in the service.env file within that directory. After any manual edits, restart to apply your changes:
claudio restartThe following variables can be set in $HOME/.claudio/service.env:
Server
PORT— HTTP server listening port. Default:8421.
Claude
MODEL— Claude model to use. Acceptshaiku,sonnet, oropus. Default:haiku. Can also be changed at runtime via Telegram commands/haiku,/sonnet,/opus.MAX_HISTORY_LINES— Maximum number of conversation messages to keep in the database. Older messages are trimmed automatically. Default:100.IS_SANDBOX— Set to1to allow Claude Code to run in sandbox mode. Automatically enabled when running as root. Optional for non-root users.
Telegram
TELEGRAM_BOT_TOKEN— Telegram Bot API token. Set automatically duringclaudio telegram setup.TELEGRAM_CHAT_ID— Authorized Telegram chat ID. Only messages from this chat are processed. Set automatically duringclaudio telegram setup.WEBHOOK_URL— Public URL where Telegram sends webhook updates (e.g.https://claudio.example.com). Set automatically when using a named tunnel.WEBHOOK_SECRET— HMAC secret for validating incoming webhook requests. Auto-generated on first run if not set.WEBHOOK_RETRY_DELAY— Seconds between webhook registration retry attempts. Default:60.
Voice (TTS/STT)
ELEVENLABS_API_KEY— API key for ElevenLabs. Required for voice messages (both TTS and STT).ELEVENLABS_VOICE_ID— ElevenLabs voice ID to use for TTS. Default:iP95p4xoKVk53GoZ742B(Chris).ELEVENLABS_MODEL— ElevenLabs TTS model. Default:eleven_multilingual_v2.ELEVENLABS_STT_MODEL— ElevenLabs STT model. Default:scribe_v1.
Tunnel
TUNNEL_NAME— Name of the Cloudflare named tunnel. Set duringclaudio install.TUNNEL_HOSTNAME— Hostname for the named tunnel (e.g.claudio.example.com). Set duringclaudio install.
Most of these variables are configured automatically by
claudio installandclaudio telegram setup. Manual editing is only needed for fine-tuning.
Claudio uses BATS (Bash Automated Testing System) for integration tests.
# Run all tests
bats tests/
# Run a specific test file
bats tests/db.batsCompleted
- Webhook signature validation
- Race conditions — Migrated from JSONL to SQLite
- Basic integration tests
- Input validation for model commands
- ShellCheck linting for scripts
- Cloudflared URL detection fails silently after 30 seconds
- Webhook health check cron job
- No retries with backoff for Telegram API
- Health check (
/health) doesn't verify actual system state - Auto-install dependencies (
sqlite3,jq,cloudflared) duringclaudio install - Show webhook registration failure reason instead of generic warning
- Add
claudioto$PATHvia symlink during install - Environment variables documentation
- Image uploads
- Voice messages from bot (TTS)
- Voice messages from human (STT)
- File uploads
Future
- Support for editing messages and reactions
- Rate limiting
- Support for group chats
Claudio is licensed under the Apache License 2.0. See the LICENSE file for details.
Contributions are welcome! Please read the CONTRIBUTING file for details on how to contribute.
Claudio is built on top of Claude and Claude Code.
