Control Claude Code and Codex CLI from Telegram. Live streaming, sessions, cron jobs, webhooks, Docker sandboxing.
Project description
Claude Code, Codex CLI, and Gemini CLI as your Telegram assistant.
Named sessions. Persistent memory. Scheduled tasks. Live streaming. Docker sandboxing.
Uses only official CLIs. Nothing spoofed, nothing proxied.
Quick start · Features · How it works · Commands · Docs · Contributing
Use your Claude Max, GPT Pro, or Gemini Pro subscription with ductor. Control your coding agents via Telegram -- automations, cron jobs, named sessions, and more.
ductor runs on your machine, uses your existing CLI authentication, and keeps state in plain JSON/Markdown under ~/.ductor/.
Quick start
pipx install ductor
ductor
The onboarding wizard handles CLI checks, Telegram setup, timezone, optional Docker, and optional background service install.
Requirements: Python 3.11+, at least one CLI installed (claude, codex, or gemini), a Telegram Bot Token from @BotFather.
Detailed setup: docs/installation.md
Why ductor?
ductor executes the real provider CLIs as subprocesses. No API proxying, no spoofing.
Other projects manipulate SDKs or patch CLIs and risk violating provider terms of service. ductor simply runs the official CLI binaries as if you typed the command in your terminal. Nothing more.
- Official CLIs only (
claude,codex,gemini) - Rule files are plain Markdown (
CLAUDE.md,AGENTS.md,GEMINI.md) - Memory is one Markdown file (
memory_system/MAINMEMORY.md) - All state is JSON (
sessions.json,cron_jobs.json,webhooks.json)
Features
Core
- Real-time streaming with live Telegram edits
- Provider/model switching with
/model(sessions are preserved per provider) @modeldirectives for inline provider targeting- Inline callback buttons, queue tracking with per-message cancel
- Persistent memory in plain Markdown
Named sessions
Run tasks in the background while you keep chatting. Each session gets a unique name and supports follow-ups:
/session Fix the login bug -> starts "firmowl" on default provider
/session @codex Refactor the parser -> starts "pureray" on Codex
/session @opus Analyze the architecture -> starts "goldfly" on Claude (opus)
/session @flash Check the logs -> starts "slimelk" on Gemini (flash)
@firmowl Also check the tests -> foreground follow-up
/session @firmowl Add error handling -> background follow-up
/sessions -> list/manage active sessions
@model shortcuts resolve the provider automatically (@opus = Claude, @flash = Gemini, @codex = Codex).
Automation
- Cron jobs: in-process scheduler with timezone support, per-job overrides, quiet hours
- Webhooks:
wake(inject into active chat) andcron_task(isolated task run) modes - Heartbeat: proactive checks in active sessions with cooldown + quiet hours
- Config hot-reload: safe fields update without restart (mtime-based watcher)
Infrastructure
- Service manager: Linux (systemd), macOS (launchd), Windows (Task Scheduler)
- Docker sandbox: sidecar container with configurable host mounts
- Auto-onboarding: interactive setup wizard on first run
- Cross-tool skill sync: shared skills across
~/.claude/,~/.codex/,~/.gemini/
How it works
graph LR
A[You on Telegram] --> B[aiogram Middleware]
B --> C[Orchestrator]
C --> D[CLIService]
D --> E[claude]
D --> F[codex]
D --> G[gemini]
E & F & G --> H[Streamed response]
H --> A
C --> I[Background Systems]
I --> J[Cron / Webhooks / Heartbeat]
I --> K[Named Sessions]
The orchestrator routes messages through command dispatch, directive parsing, and conversation flows. Background systems (cron, webhooks, heartbeat, named sessions, config reload, model caches) run as in-process asyncio tasks.
Session behavior:
- Sessions are chat-scoped and provider-isolated
/newresets only the active provider bucket- Switching providers preserves each provider's session context
Telegram commands
| Command | Description |
|---|---|
/session <prompt> |
Run named background session |
/sessions |
View/manage active sessions |
/model |
Interactive model/provider selector |
/new |
Reset active provider session |
/stop |
Abort active run |
/status |
Session/provider/auth status |
/memory |
Show persistent memory |
/cron |
Interactive cron management |
/showfiles |
Browse ~/.ductor/ |
/diagnose |
Runtime diagnostics |
/upgrade |
Check/apply updates |
/info |
Version + links |
CLI commands
ductor # Start bot (auto-onboarding if needed)
ductor stop # Stop bot
ductor restart # Restart bot
ductor upgrade # Upgrade and restart
ductor status # Runtime status
ductor service install # Install as background service
ductor service logs # View service logs
ductor docker enable # Enable Docker sandbox
ductor docker rebuild # Rebuild sandbox container
ductor docker mount /path # Add host mount
ductor api enable # Enable WebSocket API (beta)
Full CLI reference: docs/modules/setup_wizard.md
Workspace layout
~/.ductor/
config/config.json # Bot configuration
sessions.json # Chat session state
named_sessions.json # Named background sessions
cron_jobs.json # Scheduled tasks
webhooks.json # Webhook definitions
CLAUDE.md / AGENTS.md / GEMINI.md # Rule files
logs/agent.log
workspace/
memory_system/MAINMEMORY.md # Persistent memory
cron_tasks/ skills/ tools/ # Task scripts, skills, tool scripts
telegram_files/ output_to_user/ # File I/O directories
Full config reference: docs/config.md
Documentation
| Doc | Content |
|---|---|
| Developer Quickstart | Fastest path for contributors |
| Architecture | Startup, routing, streaming, callbacks |
| Configuration | Config schema and merge behavior |
| Automation | Cron, webhooks, heartbeat setup |
| Module docs | Per-module deep dives (24 modules) |
Disclaimer
ductor runs official provider CLIs and does not impersonate provider clients. Validate your own compliance requirements before unattended automation.
Contributing
git clone https://github.com/PleasePrompto/ductor.git
cd ductor
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
pytest && ruff format . && ruff check . && mypy ductor_bot
Zero warnings, zero errors.
License
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ductor-0.7.0.tar.gz.
File metadata
- Download URL: ductor-0.7.0.tar.gz
- Upload date:
- Size: 854.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5fb7cc63b578018a97be10fc643c6a54b790d26344131a2f4cb34f7df8818d61
|
|
| MD5 |
dc4f0c9fa7b3f1e58b99477d7db40123
|
|
| BLAKE2b-256 |
04b599fc4d1b5be99bddc341067a0f201a53f9c3d23660b3c785bd8207ce930d
|
Provenance
The following attestation bundles were made for ductor-0.7.0.tar.gz:
Publisher:
publish.yml on PleasePrompto/ductor
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ductor-0.7.0.tar.gz -
Subject digest:
5fb7cc63b578018a97be10fc643c6a54b790d26344131a2f4cb34f7df8818d61 - Sigstore transparency entry: 1003373235
- Sigstore integration time:
-
Permalink:
PleasePrompto/ductor@f5bb3b08a3107644340f3cbc47e4f22c72a128f6 -
Branch / Tag:
refs/tags/v0.7.0 - Owner: https://github.com/PleasePrompto
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@f5bb3b08a3107644340f3cbc47e4f22c72a128f6 -
Trigger Event:
push
-
Statement type:
File details
Details for the file ductor-0.7.0-py3-none-any.whl.
File metadata
- Download URL: ductor-0.7.0-py3-none-any.whl
- Upload date:
- Size: 959.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
199658d47532acde751215b23144fdaf91082f228849a711bf2d896cb795ebec
|
|
| MD5 |
ca5ea74511adba94d43b559d516c69af
|
|
| BLAKE2b-256 |
1f1f9f6e00f0757b19aa3a3f323d7d3b5f69588c558ed461e0ae7f44164873fc
|
Provenance
The following attestation bundles were made for ductor-0.7.0-py3-none-any.whl:
Publisher:
publish.yml on PleasePrompto/ductor
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ductor-0.7.0-py3-none-any.whl -
Subject digest:
199658d47532acde751215b23144fdaf91082f228849a711bf2d896cb795ebec - Sigstore transparency entry: 1003373242
- Sigstore integration time:
-
Permalink:
PleasePrompto/ductor@f5bb3b08a3107644340f3cbc47e4f22c72a128f6 -
Branch / Tag:
refs/tags/v0.7.0 - Owner: https://github.com/PleasePrompto
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@f5bb3b08a3107644340f3cbc47e4f22c72a128f6 -
Trigger Event:
push
-
Statement type: