Documentation

Commands

Lobby vs topic slash surface, queue, and steer.

Commands are registered in src/core/commands.ts.
Slash input never goes to the agent. Lobby commands typed inside a topic get a short “use the main chat” reply.

Lobby (root private chat)

CommandDescription
/pingLiveness → pong
/newCreate a session (repo picker). /new <repo> <name> skips the picker
/sessionsList sessions from the acpbot store
/helpLobby help

Topic (session)

CommandDescription
/cancelStop the current turn and clear the prompt queue (session kept)
/freshFresh agent session — clear conversation history, keep the topic (alias /reset; like Grok new)
/steer <text>Interrupt the current turn and inject guidance now
/queueList messages waiting until the current turn ends
/unqueueRemove queued msgs: bare = last · <n> · all
/statusContext dump: agent, launch, mode, model, effort, cwd, MCP; multi-agent parent lists children / child shows parent
/modelLLM picker buttons, or /model <value>
/effortReasoning effort picker, or /effort <level>
/agentSwitch agent process (respawn), or /agent <id>
/reviewDual-agent closeout review: /review [local|branch] [a] [b] [panel|adversarial] — see Review
/modeSession mode picker (plan/build/ask), or /mode <id> / toggle
/permissionsTool policy picker (Ask / Bypass buttons). Topic sets this session; lobby sets default + config.toml. Also /permissions ask|bypass or default ask|bypass.

Permission mode vs agent tools

AgentWhat ask does
GrokHost gates shell + file write (Telegram Allow/Reject). Agent is not started with yolo.
ClaudeSession mode set to default (not auto / bypassPermissions). Writes that go through ACP still prompt; Claude may still auto-run some built-in tools.
CodexSession mode agent (not agent-full-access). Many Codex tools run inside the adapter and may not hit Telegram.
OpenCodeMode build/plan only; tools often run in-process without ACP request_permission.

bypass skips host-side tool gates (auto-allow). Grok is not started with --always-approve / yolo — that would skip plan exit approval. See Agents → plan exit.

Permission keyboards are deleted after you answer (chat stays clean). Concurrent identical asks (e.g. parallel shell + host gate) are coalesced so you only see one prompt.

To test in Telegram (ask): prompt “run echo hello and write perm-test.txt” — Grok should show a permission keyboard; Claude should at least for write when using host fs.

CommandEffect
/planSwitch to plan mode (read-only-ish)
/buildSwitch to build/code mode (tools on); also used after a plan is ready
/skillsPick a skill, then send a prompt
/mcpRemote MCP registry + OAuth (see below)
/eveBackground directives: run / approve / status / answer a parked question — EVE
/helpTopic help (includes queue vs steer notes)

Plan ready → approve

After /plan, when the agent exits plan mode you get a Telegram Approve / Reject (plan exit is always forced to ask). Approve or /build to implement; stay in plan and keep chatting if you want changes first.

Message reactions (preference signal)

React to a bot message in a topic with any emoji (unicode or custom). The worker:

  1. Resolves the session (topic thread and/or outbound message_id index)
  2. Starts a synthetic agent turn with [telegram_reaction], including added/removed tokens and a plain-text preview of the message you reacted to (when still in the in-memory index)

No thumbs-only filter — all emojis forward. Mid-turn reactions are queued like free text. The agent process is started on demand if idle/cold. Routing uses a durable message-id map (not only “agent currently running”), so reactions still work after restart when the bot had sent that message under this worker. Use this for learning (e.g. liked a brief item); the agent maps valence, not the host.

Live “working” bubble

While a turn is in flight, the topic shows one ⏳ status message (silent notification). It updates when the agent starts tools (e.g. Running subagent…, Waiting on background tasks…, Searching the web…) and every ~15s appends elapsed time so long waits (research subagents, slow tools) don’t look frozen. Agent text lands once when the turn ends and does notify.

BubbleMeaning
⏳ Working…Turn started / between tools
⏳ Running subagent: …Background agent work
⏳ Waiting on background tasks… (1m 30s)Blocked on subagent/task output
❓ Waiting for your answer…Permission or ask_user_question

Queue vs steer (while a turn is busy)

Operator inputEffect
Free-text / mediaQueued (FIFO). Runs after the current turn ends. Does not interrupt. Ack shows a Remove button.
/steer <text>Interrupts the in-flight turn, then starts a new turn with that text. Existing queue is kept and drains after the steer turn.
/queueList waiting items (preview + index).
/unqueue / /unqueue <n> / /unqueue allRemove last / 1-based index / all.
Remove on the queue ackRemove that one item.
Delete your own Telegram messageNot supported — Bot API does not notify deletes. Use Remove or /unqueue.
/cancelAbort turn and clear the whole queue.
/fresh / /resetAbort turn + clear queue, then session/new (no history resume). Telegram topic and repo/name stay.

Cap: 32 items per session (oldest dropped when full).

/mcp subcommands

UsageEffect
/mcp statusList configured gateways for this repo
/mcp add <id> <url>Register remote MCP (id + URL in repo only); attaches empty per-topic proxy
/mcp remove <id>Remove registry entry
/mcp auth <id>Start OAuth (tappable authorize URL); live proxy picks up tools — no restart
/mcp code <callback-url>Paste-code fallback (full URL preferred)
/mcp code <code> <id>Bare code last resort

Tokens are stored under state_dir (mcp-oauth/), never in the repo. Remotes always run as acpbot mcp-proxy (empty tools until auth). Full flow: OAuth · MCP.

Telegram menu

On startup acpbot clears stale setMyCommands scopes (default + private, en) and registers the command menu from the registry so operators see lobby + topic commands in Telegram’s / UI.

Non-command input

InputHandling
Plain text in topic (idle)ACP prompt turn
Plain text in topic (turn busy)Enqueued until turn ends (see Queue vs steer)
Photo / documentSaved to .acpbot-inbox/ (or ACP attach if enabled) + prompt (or queue if busy)
VoiceSTT when configured, then prompt (or queue if busy)
Callback buttonPermission / question / mode / effort / model / agent pickers; Remove on queue acks

Wrong scope

  • Lobby command in a topic → “open the main chat”
  • Topic command in lobby → “use a session topic”
  • Unknown command → scope-aware help hint