.agents
DotAgents
Your phone buzzes with the command your agent wants to run, and two buttons: allow, deny.
the essence
Cursor or Claude Code runs on your machine. DotAgents sits beside it and hands you control through Telegram. A live message showing what the agent is doing right now. An approve request the moment it reaches for a risky command. A follow-up queued while you're away. All local: no cloud relay, code never leaves the machine.
Under the hood
Two screens, one story: Claude Code runs in the terminal on the left, you sit in Telegram on the right. The agent hit a dangerous command and froze; decide for it from your phone and watch the control loop from the inside.
Two screens, one session: Claude Code runs in the terminal on the left, you drive it from Telegram on the right, approving or denying every risky command.
How it works
- 1Claude Code works on its own in the terminal on your machine
- 2It hits a risky command: the hook pauses it and messages you in Telegram
- 3You tap Allow or Deny, and so on, until the task is done
Claude Code ·
started just now · 0 tools ·
0 files · mode: remote
Approval · a2b3c 14:33
What you approve:
Task complete
Next task:
The control channel goes to Telegram. Code, approvals and transcript stay on the machine: the API listens on 127.0.0.1 only.
Daemon mode
Changes how the next request resolves.
Security
- argon2id passcode
- HMAC + one-shot nonce
- owner-only
- audit log of decisions
- API on 127.0.0.1 only
- env stripped on spawn
- 19k+ lines
- 132 tests
- 3 migrations
- 270s long-poll
scale
size and timeframe: what stands behind the product.
architecture
Owner's phone: status, approve/deny, follow-ups
- aiogram bot polling
Long-polling: live message, HMAC buttons, modes
- FastAPI loopback spawn
Risk-call decision: mode or owner, fail-closed
- aiogram bot notify
Daemon on 127.0.0.1: sessions, events, approvals
- AgentRunner
- Approvals
Spawns the agent CLI, pumps stdout into events
- Agent CLIs subprocess
- SQLite
Fail-closed hooks in Cursor/Claude block a risky call
- FastAPI loopback approve?
claude / cursor-agent subprocesses, cwd=project
- LLM provider API
- IDE hooks pre-call
Sessions, events, approvals, nonces and audit log
Anthropic / OpenAI: called by the CLI, not the daemon
stack
- Language 1
- Framework 4
- Data 3
- Infrastructure 5
- Client 1
- AI / ML 3
Language
- Python 3.12
Framework
- aiogram 3.27
- FastAPI 0.111
- Typer
- structlog
Data
- SQLite
- SQLAlchemy 2
- Alembic
Infrastructure
- IDE hooks
- loopback API
- HMAC + nonce
- argon2id
- auto-migrations
Client
- Telegram Bot API
AI / ML
- Cursor IDE
- Claude Code CLI
- Antigravity
what it does
the product's key capabilities right now.
Approve / deny from your phone
The agent reaches for a risky command, the hook freezes it and sends a request to Telegram: the command itself and two buttons. Allow runs it, deny or silence rejects it. Fail-closed by default, not by a setting.
The before_shell and before_mcp hooks long-poll (up to ~270 seconds) and wait for a decision. Any error, timeout, or unreachable daemon is treated as deny with a non-zero exit code. The server classifies the risk: the agent can't lower it, only escalate. The same decision is available in the optional Mini App.
Live status in one message
While the agent runs, one editable message lives in the chat: what it's doing right now, which files it touches, the latest reply. The stop button is right there, no IDE needed.
LiveMessageService debounces edits (~2.5 seconds), survives 429 Retry-After and 'message not modified', and rolls overflow past 4096 characters into a second message. If a message is older than 48 hours, it sends a fresh one.
Spawn and follow-ups from the chat
You can start an agent session straight from Telegram: the /new wizard walks from project to prompt. The next task queues FIFO and reaches the agent the moment it frees up, and the transcript tail reads right there, no IDE.
The AgentRunner supervisor spawns the agent CLI as a subprocess: it feeds follow-ups to stdin, drains stderr, and pumps stdout into an event stream. FollowupService hands out tasks one at a time with row locking (skip_locked, with a SQLite fallback). Cursor history is imported, and the Claude Code transcript syncs over live SSE.
Three agents, one bridge
Hooks install into Cursor, Claude Code, and Antigravity with one Typer CLI command. For Cursor and Claude Code a session can also be spawned from Telegram; Antigravity connects through hooks only for now.
The CLI wires the hooks across all three agents and registers projects (dotagents project add). Antigravity's bot spawn waits on a headless CLI from the vendor, so for it the approve/deny loop is what's available, not launch-from-chat.
Security-first, all local
Argon2id at the gate, HMAC plus a nonce on every callback, an owner whitelist, a full audit log, and an API bound to 127.0.0.1 only. No cloud relay, and no code leaving the machine.
The nonce is one-shot and expiring, so replay and callback forgery don't get through. Before spawn the secrets (bot token, HMAC key) are stripped from the environment, cwd is forced to the project directory, shell=True is never used, and the header secret is compared in constant time.
Three modes per session
remote asks on every protected action, readonly lets it through and only notifies, standby silently rejects the dangerous. The mode switches both globally and per individual session.
AgentMode sets the ask, allow, or deny policy. Sessions live in SQLite with an idle and an absolute TTL, and SessionReaper sweeps the expired ones.
timeline
how the product grew from its first version.
-
19 Apr 2026
Stage 1: a safety bridge in a day
In a day, a scaffold and a working bridge stood up: FastAPI on loopback, an aiogram bot, SQLAlchemy 2 with Alembic. Cursor and Claude Code hooks, fail-closed approve/deny, three modes, an argon2id passcode, HMAC with a nonce, and an audit log.
-
22 Apr 2026
Stage 2: agents straight from Telegram
An agent session can be spawned from the bot: the /new wizard (project, agent, prompt), the AgentRunner subprocess supervisor, loopback spawn/input/stop commands, a project registry via CLI, and auto-migrations at startup.
-
23 Apr 2026
Telegram Mini App
An optional Mini App at /webapp: a live SSE stream, transcript, and approve/deny in a web view. Owner-only, with initData entry over HMAC.
-
29 Apr 2026
Sessions and transcript sync
Session management from the chat, inline actions (mode, refresh, stop), live Claude Code transcript sync over SSE, and an approve/deny UI in the Mini App.
-
1 Jul 2026
Hardening before release
Fail-closed hooks and pre-release hardening, a patch for vulnerable dependencies, tests fixed (140 by now), and a green audit stamp. The license moved to proprietary.
-
Next
Stage 2 remainder: voice and a universal MCP
An MCP server with notify and ask tools for Claude Code, Codex, and Gemini; voice messages via local Whisper become a command for the active session.