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