Documentation

Getting started

Binary install from GitHub Releases, setup, pair, first topic.

No Bun or source checkout required for normal use. Download a v0.4.0 release binary, run setup, pair once.

Requirements

  • A Telegram bot with Threaded Mode on in @BotFather (Bot Settings; Telegram also calls this topics in private chats)
  • Shell access on the host (to approve pairing — you do not need a Telegram user id first)
  • At least one agent CLI on PATH and logged in where required:
    • Grok Buildgrok (grok agent stdio)
    • Claudeclaude + npx (ACP adapter)
    • Codexcodex + npx (ACP adapter)
    • OpenCodeopencode (opencode acp)
    • Cursor Agentcursor-agent (cursor-agent acp; run cursor-agent login once)
    • Pipi + npx (ACP adapter pi-acp; install from pi.dev)

1. Provision the bot

@BotFather is not scriptable. Once per bot:

  1. Create a bot → copy the token
  2. Open the BotFather mini app (the Open button), pick the bot → Bot Settings → enable Threaded Mode. Chat-style BotFather commands do not always show this toggle. Telegram also calls it topics in private chats. acpbot setup checks getMe.has_topics_enabled and stops if it is false.

Pair as operator after start: DM the bot for a code, then run acpbot pair approve <code> on the host. See Pairing.

2. Download the binary

Current release: v0.4.0. Download one artifact for your platform (or use the landing page install section):

PlatformArtifactDirect link
macOS Apple Siliconacpbot-v0.4.0-darwin-arm64.tar.gz (notarized)download
macOS Intelacpbot-v0.4.0-darwin-x64.tar.gz (notarized)download
Linux x86_64acpbot-v0.4.0-linux-x64.tar.gzdownload
Linux arm64acpbot-v0.4.0-linux-arm64.tar.gzdownload

One unified binary — host and worker are subcommands of acpbot.

# Apple Silicon example (swap the asset name for your platform)
curl -fsSL -o acpbot.tar.gz \
  "https://github.com/pmdroid/acpbot/releases/download/v0.4.0/acpbot-v0.4.0-darwin-arm64.tar.gz"
tar -xzf acpbot.tar.gz
chmod +x acpbot-v0.4.0-darwin-arm64
sudo mv acpbot-v0.4.0-darwin-arm64 /usr/local/bin/acpbot   # or ~/.local/bin
acpbot help    # host, worker, setup, services, …

Checksums ship on the release (SHA256SUMS, SHA256SUMS-darwin-v0.4.0).

Config is created automatically on first start under ~/.config/acpbot/ (no manual mkdir / cp).
Full reference: Configuration.

Docker (optional)

docker pull ghcr.io/pmdroid/acpbot:v0.4.0
# or compose from the repo — see docker-compose.yml and Configuration → Docker

Image tags: v0.4.0, 0.4.0, latest. Multi-arch (linux/amd64, linux/arm64).

3. Setup + start host and worker

You need both processes: host (agents) and worker (Telegram). The worker fails at boot if the host socket is missing.

acpbot setup
# Guided TUI: bot token, agent, workspace, speech keys, optional OAuth callback.
# OAuth step can suggest Tailscale DNS / Tailscale IP / LAN IP, or a custom URL.
# macOS: offers Full Disk Access so agents can read real folders.
# Daemon step installs BOTH (same binary, two processes):
#   • acpbot host    (LaunchAgent / systemd)
#   • acpbot worker  (LaunchAgent / systemd)
ServiceCommandRole
Hostacpbot hostAgents, schedules, OAuth
Workeracpbot workerTelegram
  • macOS: app.acpbot.host + app.acpbot.worker LaunchAgents (KeepAlive)
  • Linux: acpbot-host.service + acpbot.service (systemd user)

Same ~/.config/acpbot/config.toml for both (mode 600). Logs: ~/.local/share/acpbot/logs/ on macOS, or journalctl --user -u acpbot-host -u acpbot on Linux.

Day-to-day service control (default = both host + worker):

acpbot install    # write + enable LaunchAgents / systemd units
acpbot start
acpbot stop
acpbot restart
acpbot status
# one side only: acpbot start --host   ·   acpbot stop --worker

If you skip the daemon step in setup:

acpbot host      # terminal 1 — agent stdio, schedules, OAuth
acpbot worker    # terminal 2 — Telegram

You must add a project folder before /new. Setup’s folder browser often starts in a parent like ~/code or ~/Projects. That parent is not the workspace. Browse into the project, then Use this folder. If you skip this in the wizard, /new cannot start a session until you run:

acpbot repo add
# or: acpbot repo add demo ~/code/demo
# host/worker hot-reload [repos]; no restart needed

See Repos.

Optional — install bundled skills (telegram, schedules, multi-agent, eve) into global agent dirs so Grok/Claude/… see them outside Telegram:

acpbot skills install

Background service paths: Configuration.

4. Pair as operator

The bot starts unpaired. Approve on the host CLI:

  1. Open a private chat with the bot and send any message (e.g. /ping).
  2. The bot replies with a pairing code (e.g. AB3K-9Q2M).
  3. On the machine running acpbot:
acpbot pair list
acpbot pair approve AB3K-9Q2M
acpbot pair status

Details: Pairing.

5. Add a workspace repo

/new will not create a session until [repos] has at least one entry. Each entry is one project folder, not the parent that holds many projects.

acpbot repo add
# folder browser: go into the project, then Use this folder
# or: acpbot repo add demo ~/code/demo

macOS Full Disk Access (offered in setup) only lets agents read those paths. It does not add repos. Skip the workspace step and Telegram /new replies that you need acpbot repo add first.

6. Use Telegram

/ping
/new
# pick a repo, name the session, open that topic → type a prompt

/status   /model   /effort   /agent   /mode   /skills   /mcp   /cancel
# while busy: free-text is queued; /steer <text> interrupts

On startup acpbot wipes stale setMyCommands scopes and registers the slash menu from the command registry. Slash commands never go to the agent.

CommandEffect
type textStart an ACP turn (or queue if a turn is already running)
/steer <text>Interrupt the current turn and inject guidance now
/queue / /unqueueList / remove waiting prompts
/statusAgent, model, mode, effort, cwd, MCP; spawned children / parent link when multi-agent
/modelLLM picker (or /model <id>)
/effortReasoning effort (when the agent advertises it)
/permissionsTool policy: ask (default) or bypass
/agentSwitch agent process for this session
/plan / /build / /modeSession plan/agent mode
/skillsSkill picker then prompt
/mcpPer-repo remote MCP registry + OAuth
/cancelStop current turn and clear the queue (session kept)

While a turn runs you will see a single (or ) status bubble in the topic. It updates in place as tools run. The final reply appears after the bubble is removed. Forum topic titles stay fixed (repo/name).

Busy-turn UX: free-text is queued (non-interrupt) with a Remove button on the ack; /steer … interrupts. Telegram does not notify message deletes — use Remove or /unqueue.

Details: Commands, Agents, Architecture.

7. Media & speech (optional)

DirectionBehavior
Photo / document → agentSaved under .acpbot-inbox/ (or ACP content blocks if features.acp_media_attachments = true)
Voice → agentSTT via configured provider (auto / openai / elevenlabs)
Agent → voiceMCP speak → TTS (same provider selection) → sendVoice
Agent → photo / fileMCP telegram_send_photo / telegram_send_file (path under session repo)

OpenAI-only example:

[speech]
tts_provider = "openai"
stt_provider = "openai"

[speech.openai]
api_key = "sk-…"
tts_voice = "alloy"

Full provider options: Configuration. Outbound path: Worker API.

Common failures

SymptomLikely cause
Setup or worker: topics disabledEnable Threaded Mode in @BotFather (Bot Settings), then re-run acpbot setup
/new says no reposRun acpbot repo add on the host, then /new again
No reply from non-youNot paired, or a different Telegram account
Missing bot tokenRun acpbot setup or edit ~/.config/acpbot/config.toml
Agent picker emptyNo agent CLIs on PATH (grok, claude, …)
Spawn dies immediatelyCheck agent login / adapter; stderr is logged
OAuth / host divergeWorker and host must share the same state_dir / config file
acpbot host exits on bootOAuth listen port in use, or missing shared state dir
Speech silent / no STTSet [speech.openai] or [speech.elevenlabs] keys; check tts_provider / stt_provider

From source (developers only)

Binary installs do not need Bun. For contributors, build or run via Bun, but all operator commands stay acpbot:

git clone https://github.com/pmdroid/acpbot.git
cd acpbot
bun install
bun run build:compile    # → dist/acpbot
# or during dev: bun run src/main.ts <command>

acpbot skills install    # global agent skills
acpbot host              # terminal 1
acpbot worker            # terminal 2
bun test ./test
bun run typecheck

Next