network-user
back to all projects
Tool 19 Apr 2026 beta

.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.

Your machine
claude - agent session
claude-opus · 0 tool calls
Your phone
DotAgents bot

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.

10 дней of active build from first commit to a working MVP, then polish
~18k lines of Python with tests
33 commits in a single repository
140 pytest tests
15 commands in the Telegram bot
localhost loopback: code never leaves the machine

architecture

loopback daemon polling spawn subprocess API pre-call approve? notify Telegram aiogram bot Approvals FastAPI loopback AgentRunner SQLite IDE hooks Agent CLIs LLM provider

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

Tap a module to see its role in the system.

stack

stack by layer · 17
  • 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.

  1. 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.

  2. 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.

  3. 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.

  4. 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.