A Telegram bridge for Claude Code. Give your CLI assistant a phone number.
OpenDitto turns Claude Code — Anthropic's command-line AI assistant — into a personal bot you can reach from Telegram. Your assistant runs on your Mac, answers messages from anywhere, remembers everything across restarts in an Obsidian vault you control, and has access to the full Claude Code toolkit (every MCP, skill, and subagent you already use locally).
Built for solopreneurs, indie hackers, and anyone who wants a second self they can text from their phone.
- Telegram bot locked to only your account — nobody else can reach it
- Runs locally on your Mac — no cloud, no monthly hosting, nothing leaves your machine
- Persistent memory stored as markdown in an Obsidian vault; browse and edit the bot's knowledge like any other notes
- 24/7 uptime with auto-restart wrapper, idle-sleep prevention, and a daily 4am context reset
- Full Claude Code toolkit — every MCP, skill, and subagent your local Claude Code has access to, reachable by text message
- Manual
/freshto reset context between tasks,/ctxto check context window usage - Automatic
brew upgradeon every daemon restart so you're always on the latest Claude Code release
OpenDitto is a documented recipe with an interactive installer. It assembles Anthropic's official Telegram channel plugin + Obsidian + a small set of scripts and configs into a working always-on assistant.
No programming experience required. No cloud accounts. No monthly hosting. Just your Mac, a Claude Pro or Max subscription, and a Telegram account.
If you just want the bot running: run this in Terminal on your Mac:
bash -c "$(curl -fsSL https://raw.githubusercontent.com/regreenjr/openditto/main/install.sh)"The installer handles everything automatically where it can (Homebrew, Bun, Obsidian, Claude Code, all config files, the LaunchAgent) and walks you through the manual steps (Telegram bot creation, Claude login, bot pairing) with clear prompts. 15–25 minutes total, most of which is waiting for things to install.
- Checks macOS version and installs missing dependencies (Homebrew, Bun, Obsidian, Claude Code,
expect) - Creates the daemon working directory and downloads the config templates
- Creates an Obsidian vault and pre-wires the memory symlink so it works from turn zero
- Walks you through subscribing to Claude Pro (if needed) and running
claude /login - Guides you through creating a Telegram bot in @BotFather, verifies the token against Telegram's API before continuing
- Uses
expect(1)to drive Claude Code's interactive TUI and install the Telegram plugin - Launches the daemon once to capture your pairing code, then automatically locks the allowlist policy
- Installs and loads the 4am daily auto-restart LaunchAgent
The installer can be re-run safely — steps that are already done are detected and skipped.
Sensible. Download it, read it, then run:
curl -fsSL https://raw.githubusercontent.com/regreenjr/openditto/main/install.sh -o ~/openditto-install.sh
less ~/openditto-install.sh # or open in your editor
bash ~/openditto-install.shFall back to the manual tutorial (TUTORIAL.md). It walks through every step in detail, no automation, guaranteed to work if you follow it carefully. The installer is a convenience — the tutorial is the source of truth.
The installer prints specific failure messages pointing to the relevant TUTORIAL.md section whenever a step fails, so you can pick up the manual path right where the automated one stopped.
Full setup tutorial → TUTORIAL.md
The tutorial assumes zero terminal experience and walks through every command. It's the complete reference: exactly what the installer does, why each step matters, and how to recover if something goes wrong. Read it if:
- The installer failed and you need to figure out which step
- You want to understand the architecture before installing
- You want to customize or modify the setup
- You don't trust
curl | bash(reasonable) and would rather type each command yourself
A rendered HTML version is in docs/tutorial.html — easier to read, shareable with friends who find markdown unfriendly.
Skip the tutorial and grab the config templates directly:
templates/CLAUDE.md— the daemon's system prompt (channel-routing rules, memory discipline,/freshand/ctxcommands, automatic context warnings)templates/start-daemon.sh— 24/7 wrapper script withcaffeinate -i,brew upgrade, and auto-restarttemplates/ctx— Python script that reports current context window usagetemplates/com.openditto.daemon-restart.plist— launchd user agent for the 4am daily restart
Drop them into ~/claude-daemon/ and ~/Library/LaunchAgents/, adjust the label if needed, and you're running.
bash -c "$(curl -fsSL https://raw.githubusercontent.com/regreenjr/openditto/main/uninstall.sh)"Removes the daemon, LaunchAgent, bot token, and Claude Code project directory. Does not touch your Obsidian vault (your memory — that's your data), Homebrew, Bun, Obsidian, or Claude Code itself.
- macOS Sonoma (14) or newer
- Claude Pro or Max subscription (required to authenticate Claude Code; $20+/month)
- Telegram account
- ~60–90 minutes of setup time
Read this before you install.
OpenDitto runs Claude Code with --dangerously-skip-permissions, which means your bot has unrestricted access to your Mac: it can read and write any file in your home folder, run any shell command, reach any service Claude Code is connected to (GitHub, email, databases, etc.), and spend your Anthropic subscription quota.
The Telegram sender allowlist — locked to your Telegram account only — is the single gate between the outside world and your Mac. If your Telegram account is compromised, an attacker has effectively full control of your machine via text message.
Mitigate by:
- Using a strong password + two-factor authentication on your Telegram account
- Never sharing your bot's username publicly
- Reviewing
~/Library/Logs/claude-daemon-wrapper.logperiodically - Stopping the daemon (Ctrl+C in its terminal window) any time you don't need it running
- Not installing this if the above trade-off makes you uncomfortable
See the full trust model section in the tutorial.
OpenDitto composes three pieces:
- Claude Code running in interactive mode with the channels primitive enabled. The channels primitive lets an MCP server push inbound events (Telegram messages) into a running Claude session, wrapped in
<channel source="telegram" chat_id="..."/>tags. - Anthropic's official Telegram channel plugin, which runs as a Bun subprocess of Claude Code. It polls Telegram's API, forwards inbound messages into the session, and exposes a
replytool so Claude can send messages back. - A small set of macOS glue — a bash wrapper for 24/7 uptime and auto-updates, a launchd plist for scheduled daily restarts, a Python script for context-usage reporting, and a symlink from Claude Code's auto-memory to an Obsidian vault.
The architecture intentionally accepts a single-session design: all Telegram chats flow into one Claude Code context, and chats are partitioned by chat_id via prompt instructions plus memory frontmatter rather than by separate sessions. The daily 4am restart enforces this model by making in-context history disposable — memory on disk is the only durable layer.
- OpenClaw by Peter Steinberger — the original file-based memory + per-chat Telegram context pattern. OpenDitto replicates that experience using Claude Code primitives.
- Anthropic — for building Claude Code, the channels primitive, and the official Telegram plugin that makes this possible.
- Obsidian — the markdown vault that becomes the bot's memory.
OpenDitto is not affiliated with or endorsed by Anthropic, the OpenClaw project, or Obsidian.
Issues and PRs welcome for tutorial improvements, troubleshooting additions, and platform-specific fixes — especially from anyone who has followed the tutorial on a fresh Mac and hit a snag I didn't. See CONTRIBUTING.md.