Use Claude Code from your phone via Telegram. Multi-project sessions, owner-gated, customizable persona.
Project description
domlabs-bot
Use Claude Code from your phone. Ship from anywhere.
A self-hosted Telegram bridge that lets you chat with Claude Code on your laptop from your phone. Persistent multi-project sessions, owner-gated, fully-customizable persona.
Prerequisites
Before you install, you need:
- Python 3.10 or newer —
python --versionto check. - An Anthropic API key — get one at https://console.anthropic.com/settings/keys.
- Telegram (desktop, web, or mobile) — to message @BotFather and create your bot.
pipx(recommended). If you don't have it:python -m pip install --user pipx python -m pipx ensurepath # restart your terminal so PATH picks up pipx
Install
The fastest path — clone the repo, run the setup script, and chain straight into the wizard:
# macOS / Linux
./setup.sh --init
# Windows (PowerShell)
.\setup.ps1 -Init
The script:
- Auto-installs
pipxif it's missing. - Runs
pipx install -e . --forceagainst this directory. - Filters pipx's noisy
done! ✨ 🌟 ✨line out of the output. - Optionally chains into
domlabs-bot init(--init/-Initflag).
Or, if you'd rather drive pipx yourself:
pipx install domlabs-bot
domlabs-bot init
domlabs-bot start
That's it. The init wizard walks you through:
- Anthropic API key (validated against the API)
- Pick a model (defaults to Sonnet 4.6; choose Opus, Haiku, or a custom ID)
- Creating a Telegram bot via BotFather (validated with
getMe) - Owner identification — your bot opens; you send the message
pair; the wizard auto-detects your Telegram user ID. No third-party detour. - Persona setup (optional, skippable)
- Project paths the bot can switch between
Everything lives under ~/.domlabs-bot/. Set DOMLABS_BOT_ROOT to put it
elsewhere.
Run on boot
domlabs-bot start --daemon # install + start as an OS service
domlabs-bot status # check it's healthy
domlabs-bot stop # halt it
domlabs-bot uninstall-daemon # remove the service definition
domlabs-bot logs -f # tail the log file
Daemon installer:
- Windows — registers a per-user Scheduled Task (logon trigger, hidden, restart on failure)
- macOS — writes
~/Library/LaunchAgents/com.domlabs.bot.plistand bootstraps it vialaunchctl - Linux — writes
~/.config/systemd/user/domlabs-bot.serviceand enables it. Runloginctl enable-linger $USERif you want it to survive logout.
How it works
Telegram ──► python-telegram-bot poller ──► SessionManager ──► Claude Agent SDK ──► claude CLI
▲
│
per-project sessions, idle-recycled,
auto-summarised to ~/.domlabs-bot/memory/
- One persistent Claude session per project.
/project nameswitches the current target. - Voice notes (optional) → Gemini transcription → session.
- Photos → vision-enabled multi-modal turn → session.
- Idle sessions are summarised into the daily memory file before disposal.
- The agent has Telegram-aware tools (
mcp__telegram__send_file,send_photo,send_code_as_file) for delivering large/binary results.
MCP servers
The bot ships with one in-process MCP server (telegram, exposing the
send-file/photo/code tools above) and inherits every other MCP server
you've registered with Claude Code. The session is created with
setting_sources=["user", "project", "local"], so anything in your
claude mcp list is available inside Telegram conversations.
To add more — e.g. Playwright, GitHub, Linear, your own — register them the normal way:
claude mcp add playwright --scope user -- npx @playwright/mcp@latest
claude mcp list # confirm it's connected
domlabs-bot stop && domlabs-bot start --daemon # restart so the bot picks it up
Security note. Whatever MCP servers you have registered are reachable via your phone over Telegram. If you've connected MCPs that hold tokens (GitHub PATs, Linear keys, internal company servers), the owner of this bot can drive them. Audit
claude mcp listbefore runningstart, and keepOWNER_USER_IDcorrect so only you can talk to the bot.
Persona — bring your own
init scaffolds four files under ~/.domlabs-bot/ you can edit by hand:
IDENTITY.md— your assistant's name + vibe (the runtime parses these and templates them into the system prompt)USER.md— your name + anything you want the assistant to know about youSOUL.md— personality core, principles, taste. The agent reads it on demand.MEMORY.md— long-term curated facts and project state. The agent may update this; it will never autonomously editSOUL.md,IDENTITY.md, orUSER.md.
You can skip the persona during init. The bot still works — it just
addresses you as "you" and runs without character.
Voice (optional)
Voice notes in / TTS replies out are gated behind an extras install:
pipx install 'domlabs-bot[voice]'
# then in ~/.domlabs-bot/.env:
VOICE_ENABLED=true
GEMINI_API_KEY=your-key-here
Toggle reply mode from Telegram: /voice on, /voice once, /voice off.
Configuration
Hand-edit ~/.domlabs-bot/.env for things the wizard doesn't ask:
IDLE_TIMEOUT_MINUTES=15 # session recycle threshold
MODEL=claude-sonnet-4-6 # override default model (the wizard sets this)
CLAUDE_CLI_PATH=/usr/local/bin/claude # if not on PATH
DEFAULT_CWD=/Users/me/code # session default
Telegram commands
/start — banner + commands
/status — session state
/project — list / switch / add / rm projects
/new — fresh session for the current project
/mem <text> — quick-append to today's daily memory
/voice on|off|once — voice replies
Plain text, photos, and voice notes route to the current project session.
Troubleshooting
domlabs-bot: command not found after install.
Pipx put the script in a directory not on your PATH. Run pipx ensurepath and restart your terminal. On Windows, the directory is typically %USERPROFILE%\.local\bin.
The bot isn't replying. Two common causes:
- Another process is polling the same bot token (e.g. an older
cc-telegraminstance, or a seconddomlabs-bot start). Only one poller is allowed per bot.domlabs-bot stopto halt the daemon, or kill the conflicting process. - The wizard's owner-detect grabbed the wrong user ID. Check
OWNER_USER_IDin~/.domlabs-bot/.envagainst your Telegram ID. Re-rundomlabs-bot initto reconfigure (your old config is backed up to~/.domlabs-bot.bak/).
The wizard hangs on Step 4 ("Waiting for the 'pair' message").
You're expected to open your new bot in Telegram and send the literal word pair. The wizard polls Telegram's getUpdates for that message. Cap is 10 minutes — Ctrl+C to abort, then re-run.
Anthropic key validation fails with HTTP 4xx. 401/403 means the key is wrong or revoked — generate a fresh one. Anything else (404, 5xx, network) means something rare happened; the wizard will let you proceed without validating.
Logs.
The bridge writes to ~/.domlabs-bot/logs/domlabs-bot.log. Tail it live with:
domlabs-bot logs -f
Reset everything.
domlabs-bot uninstall-daemon
rm -rf ~/.domlabs-bot
Then domlabs-bot init to start fresh.
Roadmap
- v1.1: Homebrew tap
- v2: domlabs-bot-control (Windows screen + UIA control via MCP)
Contributing
Issues and PRs welcome at https://github.com/johnniedom/domlabs-bot.
License
MIT — see LICENSE.
Not affiliated with Anthropic. Claude is a trademark of Anthropic, PBC. Built by Dom Labs.
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 domlabs_bot-0.1.0.tar.gz.
File metadata
- Download URL: domlabs_bot-0.1.0.tar.gz
- Upload date:
- Size: 35.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2dc386e0506c0b5621f9248a84700cacfdf5c1332d417e0c91b6bb21abb5c94c
|
|
| MD5 |
bd55337e19f8f9e310fdd89d139ce53c
|
|
| BLAKE2b-256 |
f4dfa5fccabb70b5af1fec677a0d52dfc7c609040bb9f83f325278fd13e9d2f8
|
Provenance
The following attestation bundles were made for domlabs_bot-0.1.0.tar.gz:
Publisher:
publish.yml on johnniedom/domlabs-bot
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
domlabs_bot-0.1.0.tar.gz -
Subject digest:
2dc386e0506c0b5621f9248a84700cacfdf5c1332d417e0c91b6bb21abb5c94c - Sigstore transparency entry: 1438688576
- Sigstore integration time:
-
Permalink:
johnniedom/domlabs-bot@796ea2d438b520988815a367369077e506d6fcec -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/johnniedom
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@796ea2d438b520988815a367369077e506d6fcec -
Trigger Event:
push
-
Statement type:
File details
Details for the file domlabs_bot-0.1.0-py3-none-any.whl.
File metadata
- Download URL: domlabs_bot-0.1.0-py3-none-any.whl
- Upload date:
- Size: 46.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2b63313391bb4d67c1d1ce9fdd07075302a67ba82fb790da27a30ba60c135efa
|
|
| MD5 |
b3edf84c27f9ee86bb6ae21d56008254
|
|
| BLAKE2b-256 |
4fb3ee8c9605c1e8c36665ffcd1d919602998b44aace2ca0935c87b08bea89ef
|
Provenance
The following attestation bundles were made for domlabs_bot-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on johnniedom/domlabs-bot
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
domlabs_bot-0.1.0-py3-none-any.whl -
Subject digest:
2b63313391bb4d67c1d1ce9fdd07075302a67ba82fb790da27a30ba60c135efa - Sigstore transparency entry: 1438688577
- Sigstore integration time:
-
Permalink:
johnniedom/domlabs-bot@796ea2d438b520988815a367369077e506d6fcec -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/johnniedom
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@796ea2d438b520988815a367369077e506d6fcec -
Trigger Event:
push
-
Statement type: