• Joined on 2024-02-27

telegram-acp (0.2.0)

Published 2026-05-10 14:47:39 +02:00 by mats

Installation

[registry]
default = "gitea"

[registries.gitea]
index = "sparse+https://git.k6n.net/api/packages/mats/cargo/" # Sparse index
# index = "https://git.k6n.net/mats/_cargo-index.git" # Git

[net]
git-fetch-with-cli = true
cargo add telegram-acp@0.2.0

About this package

Bridge Telegram and ACP coding agents

Telegram-ACP

Control any coding agent through Telegram.

Screenshots Screenshots Screenshots
photo_1_2026-03-14_01-08-15 photo_2_2026-03-14_01-08-15 photo_2026-03-14_01-13-09
Talking with agent.
Handle multiple sessions with tabs and threads.
Uploading artifacts.
Use telegraph to view your markdown files, or let it upload images or files.
Slash commands.
Manage your sessions with ease, set models and permissions, or use agent's commands.

Features

  • Get notifications and view real-time progress on your phone
  • Give new tasks to agent even you're away from computer
  • Works with any agent that supports ACP. This is almost any agent, including claude code, codex, opencode and cursor.
  • Handle multiple sessions simutaniously, in different telegram tabs

Installation

Method 1: Use cargo binstall (not recommended)

cargo binstall requires me to manually bump version numbers and do a release, and there's no way to upload a binary on push. Therefore, the version on binstall can be quite old.

cargo binstall telegram-acp
telegram-acp

Method 2: Use via nix

nix run github:SuperKenVery/Telegram-ACP

Method 3: Compile from source

git clone https://github.com/SuperKenVery/Telegram-ACP.git
cd Telegram-ACP
./dev-loop.fish

Configuration

On Telegram, use @botfather to create a new bot and get your bot token. You should also enable threaded mode in bot settings.

Create ~/.config/telegram-acp/config.toml:

bot_token = "<telegram-bot-token>"
chat_id = 123456789
default_agent = "claude"
# websocket_bind = "127.0.0.1:9001"

[claude]
cmd = "claude-agent-acp"

[codex]
cmd = "codex --acp"
# socket_path = "/tmp/telegram-acp.sock"
# telegraph_author = "Your Name"

Env overrides are also supported:

  • TELEGRAM_ACP_BOT_TOKEN
  • TELEGRAM_ACP_CHAT_ID
  • TELEGRAM_ACP_SOCKET_PATH
  • TELEGRAM_ACP_WEBSOCKET_BIND
  • TELEGRAM_ACP_DEFAULT_AGENT
  • TELEGRAM_ACP_TELEGRAPH_AUTHOR

When websocket_bind is set, the daemon starts a websocket listener and broadcasts each SessionEvent as a JSON text frame. The stream includes user prompts, agent updates, and session lifecycle events for every thread.

Hacking

How it works

CLI ──(Unix socket IPC)──> Daemon ──> ACP Agent subprocesses (stdin/stdout)
                              │
                              ├──> Telegram Bot API (topics, messages)
                              └──> Websocket listeners (session event stream)

Per session:

  1. Creates/uses a Telegram forum topic (or threaded private chat topic)
  2. Spawns an ACP agent subprocess
  3. Routes user messages -> agent and agent events -> Telegram
  4. Optionally broadcasts the same session activity to websocket listeners

Mock agent testing

Use the included mock ACP binary to test Telegram/IPC plumbing without a real coding agent:

cargo run -- daemon

Configure it as an agent in your config:

default_agent = "mock"

[mock]
cmd = "./target/debug/mock_agent"

Then you can send some ACP updates as text via telegram, and it would send those updates to our daemon.

Telegram requirements

  • Enable Threaded Mode in BotFather
  • For supergroups, forum topics should be enabled

Some design decisions

  • agent-client-protocol types are !Send, so ACP work is pinned to a tokio::task::LocalSet
  • Telegram dispatcher + IPC server run with tokio::spawn and communicate through channels
  • Each session has two unbounded channel pairs:
    • user_tx/user_rx: user text into prompt loop
    • event_tx/event_rx: agent output back to Telegram consumer
  • A daemon-scoped SessionEvent relay fans out session activity to optional websocket listeners
  • Notification behavior is intentional:
    • first and final message notify
    • intermediate streaming messages are silent
  • Permission prompts are auto-approved by choosing the first allow option

Project layout

src/
  main.rs          CLI entrypoint (`daemon`, `new`, `status`)
  config.rs        Config loading (TOML + env overrides)
  daemon.rs        Daemon state, session lifecycle, LocalSet bridge
  session.rs       Prompt loop (PromptRequest orchestration)
  acp.rs           ACP client integration + subprocess handling
  relay.rs         SessionEvent model and fan-out sinks
  telegram.rs      Bot dispatcher, topic routing, event consumer
  telegraph.rs     Telegraph helpers (account/page publishing)
  ipc.rs           Unix socket NDJSON daemon/client protocol
  types.rs         Shared command/response/event types
  websocket.rs     Websocket broadcaster for SessionEvent listeners
  formatting.rs    Telegram HTML escaping + message splitting
  bin/mock_agent.rs Mock ACP agent for local testing

License

GPL v3

Dependencies

ID Version
agent-client-protocol ^0.10
anyhow ^1
async-trait ^0.1
base64 ^0.22
chrono ^0.4
clap ^4
dashmap ^6
dirs ^5
futures ^0.3
if-addrs ^0.13
mdns-sd ^0.13
platform-dirs ^0.3
pulldown-cmark ^0.10
reqwest ^0.12
rmcp ^1.2
rolling-file ^0.2
schemars ^1
serde ^1
serde_json ^1
similar ^2
telegram-markdown-v2 ^0.2
telegraph-rs ^0.6
teloxide ^0.17
thiserror ^2
tokio ^1
tokio-tungstenite ^0.24
tokio-util ^0.7
toml ^1.0
tracing ^0.1
tracing-subscriber ^0.3
uuid ^1
Details
Cargo
2026-05-10 14:47:39 +02:00
2
MIT
110 KiB
Assets (1)
Versions (1) View all
0.2.0 2026-05-10