把手机当作 Claude Code 的远程入口:手机上语音转文字 → 发给 Telegram Bot → bridge 在你的开发机上启动一个 Claude Code 会话替你执行。读文件、改代码、跑命令、看 diff,结果切片回传到 Telegram。
典型场景
- 躺在床上 / 沙发上继续白天没写完的功能
- 通勤路上让 Claude 在公司机器上跑测试 / 改 PR
- 离开座位时用手机推进任务,回来直接看结果
- 🎙️ 为语音设计:命令短、好念(
/proj teleop、/session work、/model haiku) - 🔀 多 session 并行:一个项目里维持多个独立的 Claude 对话,互不污染上下文
- 💾 断电不丢历史:session_id 落盘,bridge 重启 / 进程崩溃后能续接 Claude 完整对话
- 🧠 每 session 独立模型:
main用 Opus、quick用 Haiku,灵活省 token ⚠️ 危险操作二次确认:Bash/Write/Edit/NotebookEdit强制/yes确认,5 分钟超时默认拒绝- 🔒 chat_id 白名单:只有你自己的 Telegram 账号能驱动 bridge
- 🚀 运行时加项目:命令行
teleop add或 bot 内/addproj,不用改配置、不用重启 bridge - 📦 uv 全程管理:单文件 +
pyproject.toml,几条命令装完跑
手机 (语音 → 文本)
│
▼
Telegram Bot ─────► bridge.py ─────► Claude Agent SDK ─► Claude Code CLI
▲ │
└──── 回复 ───────┘
一个 Telegram chat ⇄ 多个命名 session(按项目分组)。每个 session 是一个独立的 ClaudeSDKClient,拥有自己的对话历史;切 session 不影响其他 session 的状态。
前置依赖
- Python ≥ 3.10
uv管理 Python 环境- Claude Code CLI 已登录:
npm i -g @anthropic-ai/claude-code - 从 @BotFather 拿到的 Telegram Bot token
安装
git clone https://github.com/weishuaiSong/teleop-cc.git
cd teleop-cc
uv sync
cp .env.example .env # 编辑 .env,填 token 和项目路径
uv run python bridge.py首次启动获取 chat_id
如果你还不知道自己的 chat_id:
.env里先填ALLOWED_CHAT_IDS=0,启动 bridge- Telegram 里给你的 Bot 发
/id(这条命令故意不做鉴权) - 把回的 chat_id 填回
.env,重启
修个 typo
你 把 bridge.py 里 main 函数那个 typo 修了,是 Aplication 拼错
Bot 🔧 Grep Aplication
Bot 🔧 Read bridge.py:660-680
Bot ⚠️ [teleop/main] Edit
C:\work\teleop\bridge.py
/yes a1b2c3 | /no a1b2c3
你 /yes a1b2c3
Bot 🔧 Edit C:\work\teleop\bridge.py
Bot 已修复 line 663:Aplication → Application
切模型省 token
你 /model haiku
Bot → [teleop/main] model=haiku
你 列一下当前所有 .md 文件
Bot 🔧 Glob *.md
Bot 找到 2 个文件: README.md, LICENSE
多 session 并行
你 /session debug
Bot → [teleop/debug]
你 跑一下 pytest 看看
Bot 🔧 Bash pytest -q
...
你 /session main
Bot → [teleop/main]
你 继续刚才那个重构,把 ChatState 抽成单独的文件
不需要 bridge 在跑,也能管理项目列表;改完 bridge 立即可见,不用重启。
| 命令 | 作用 |
|---|---|
uv run python bridge.py |
启动 bridge(无 subcommand) |
uv run python bridge.py add [名字] |
注册当前目录为项目(默认别名 = 目录名) |
uv run python bridge.py add 别名 --path C:\path |
注册任意路径 |
uv run python bridge.py rm 别名 |
删除一个运行时项目 |
uv run python bridge.py list |
列出所有项目(.env + 运行时) |
全局安装让 teleop 在任何目录可用:
uv tool install --editable .
uv tool update-shell # 第一次需要,把 ~/.local/bin 加进 PATH
# 重开终端
cd C:\work\some-project
teleop add # 一行加进项目列表
teleop list| 命令 | 作用 |
|---|---|
/id |
显示当前 chat_id(无鉴权,首次发现用) |
/whoami |
显示 chat / project / session / model / cwd |
/projects |
列出所有项目(标注 .env / live) |
/proj <别名> |
切到对应项目 |
/addproj <别名> <路径> |
运行时新增一个项目 |
/rmproj <别名> |
移除一个运行时项目 |
/sessions |
列出当前项目下所有 session |
/session <名字> |
切到/新建一个命名 session |
/drop <名字> |
删除一个 session(内存 + 落盘) |
/model [名字] |
显示或切换当前 session 的模型 |
/models |
列出已知模型别名 |
/new |
重置当前 session(清空历史) |
/yes <token> / /no <token> |
确认/拒绝危险工具调用 |
| (普通文字) | 作为下一轮用户消息发给当前 session |
/sessions 输出示例:
[teleop]
* ● 💾 main
○ 💾 debug
● 💾 quick
(* current ● in-memory 💾 persisted)
*当前活跃 session●内存里有 live SDK client💾落盘过,下次/session切过去会 resume 完整历史
TELEGRAM_BOT_TOKEN=<@BotFather 给的 token>
ALLOWED_CHAT_IDS=<你的 chat_id,多个用逗号分隔>
PROJECTS=teleop=C:\work\teleop,foo=C:\path\to\fooPROJECTS 第一条是默认项目(启动时落到这里)。.env 里的项目优先级高于 projects.json,不能用 /rmproj 或 teleop rm 删。
/addproj 和 teleop add 加的项目落到这里:
{
"myproj": "C:\\path\\to\\myproj"
}每个 session 第一次有回复后 session_id 和 model 写入:
{
"8285174078": {
"teleop": {
"main": { "id": "33ecb5f9-...", "model": null },
"debug": { "id": "abcd1234-...", "model": "haiku" }
}
}
}bridge 重启 → /session main → SDK 用 resume="33ecb5f9-..." 续上完整对话。
- chat_id 白名单:除
/id外所有命令要求chat_id ∈ ALLOWED_CHAT_IDS - 危险工具拦截:
Bash/Write/Edit/NotebookEdit经can_use_tool回调发到 Telegram,需要/yes <token>确认,5 分钟超时默认拒绝 - 只读工具放行:
Read/Glob/Grep等不弹确认 - token 随机:6 位十六进制,每次工具调用现生成
威胁模型限定单用户、可信开发机。bridge 进程在开发机以你的权限运行 Claude Code,等同你账号本人。不要在不信任的机器上跑、不要泄露 Bot token。
.
├── bridge.py # 单文件 bridge
├── pyproject.toml # uv 管的元数据 + 依赖
├── uv.lock
├── .env.example
├── sessions.json # 自动生成
├── projects.json # 自动生成
├── LICENSE
└── README.md
启动卡住,getMe ConnectTimeout
代理和 api.telegram.org 握手超时。换节点或重连梯子再启动。
Bot 没反应
- 看日志有没有
Application started - 看日志里有没有
unauthorized chat=xxx——chat_id 没进白名单
/sessions 显示 ○ 💾 main 但发消息后没历史
SDK resume 极少数情况会失败,会自动降级为新建 session 并清掉那条 sessions.json 记录。日志里会看到 resume failed for ..., falling back to new session。
teleop 命令找不到
uv tool install --editable . 之后要 uv tool update-shell + 重开终端。已开窗口认不到新 PATH。
- inline keyboard 按钮代替
/yes/no(语音场景更省事) -
/import <session-id>把 IDE Claude 的会话接到 bot - TTS 回传:让 bot 用语音念回复,开车通勤场景更友好
- Linux / macOS 验证(当前在 Windows 11 跑通)
MIT © 2026 Weishuai Song
A Telegram-to-Claude-Code bridge for voice-driven development. Speak into any voice-to-text app on your phone, send the text to a Telegram bot, and Claude Code runs against your project on a remote machine. Read files, edit code, run commands, review diffs — all streamed back as chat messages.
Typical scenarios
- Keep coding from the couch / bed when you're done sitting at the desk
- On the commute: have Claude run tests or update a PR on your office machine
- Away from the keyboard: nudge tasks forward by phone, review when you're back
- 🎙️ Voice-first ergonomics — short, speakable commands (
/proj teleop,/session work,/model haiku) - 🔀 Multiple sessions per project — independent Claude conversations that don't pollute each other's context
- 💾 Survives restarts — session IDs are persisted, the bridge resumes Claude's full history after a restart
- 🧠 Per-session model — pin
mainto Opus,quickto Haiku ⚠️ Safety gate —Bash/Write/Edit/NotebookEditrequire an explicit/yesconfirmation in chat- 🔒 Chat-ID whitelist — only your own Telegram account talks to the bridge
- 🚀 Live project registration — add a project via
teleop addfrom any terminal, or/addprojfrom the bot, no restart needed - 📦 uv all the way — one file, one
pyproject.toml, a few commands and you're running
Phone (voice → text)
│
▼
Telegram Bot ─────► bridge.py ─────► Claude Agent SDK ─► Claude Code CLI
▲ │
└─── replies ────┘
One Telegram chat ⇄ many named Claude sessions, scoped per project. Each session is an independent ClaudeSDKClient with its own history; switching sessions doesn't affect the others.
Prerequisites
- Python ≥ 3.10
uvfor dependency management- Claude Code CLI authenticated:
npm i -g @anthropic-ai/claude-code - A Telegram Bot token from @BotFather
Install
git clone https://github.com/weishuaiSong/teleop-cc.git
cd teleop-cc
uv sync
cp .env.example .env # edit .env, fill in token and project paths
uv run python bridge.pyFirst-run: discovering your chat_id
- Set
ALLOWED_CHAT_IDS=0in.envand start the bridge. - In Telegram, open your bot and send
/id. The/idcommand is intentionally unauthenticated. - Paste the returned id into
.envand restart.
Fix a typo
You Fix the typo in bridge.py main(): "Aplication" should be "Application"
Bot 🔧 Grep Aplication
Bot 🔧 Read bridge.py:660-680
Bot ⚠️ [teleop/main] Edit
C:\work\teleop\bridge.py
/yes a1b2c3 | /no a1b2c3
You /yes a1b2c3
Bot 🔧 Edit C:\work\teleop\bridge.py
Bot Fixed line 663: Aplication → Application
Switch model to save tokens
You /model haiku
Bot → [teleop/main] model=haiku
You List all markdown files
Bot 🔧 Glob *.md
Bot Found 2: README.md, LICENSE
Parallel sessions
You /session debug
Bot → [teleop/debug]
You Run pytest please
Bot 🔧 Bash pytest -q
You /session main
Bot → [teleop/main]
You Continue the refactor — extract ChatState into its own file
You don't need the bridge running to manage projects; changes are picked up live — no restart needed.
| Command | Effect |
|---|---|
uv run python bridge.py |
Start the bridge (no subcommand) |
uv run python bridge.py add [name] |
Register cwd as a project (alias defaults to the directory name) |
uv run python bridge.py add name --path C:\path |
Register an arbitrary path |
uv run python bridge.py rm name |
Remove a runtime project |
uv run python bridge.py list |
List all projects (env + runtime) |
For a globally available teleop command:
uv tool install --editable .
uv tool update-shell # first time only — adds ~/.local/bin to PATH
# reopen terminal
cd C:\work\some-project
teleop add # one-liner project registration
teleop list| Command | Effect |
|---|---|
/id |
Reply with chat_id (no auth). |
/whoami |
Show chat / project / session / model / cwd. |
/projects |
List configured projects (annotated .env / live). |
/proj <name> |
Switch project. |
/addproj <name> <path> |
Register a new project at runtime. |
/rmproj <name> |
Remove a runtime project. |
/sessions |
List sessions in the current project. |
/session <name> |
Switch to / create a named session. |
/drop <name> |
Delete a session (memory + persisted id). |
/model [name] |
Show or switch the current session's model. |
/models |
List known model shortcuts. |
/new |
Reset the current session (clear history). |
/yes <token> / /no <token> |
Approve / deny a pending dangerous tool call. |
| (plain text) | Sent to the current session as the next user message. |
Example /sessions output:
[teleop]
* ● 💾 main
○ 💾 debug
● 💾 quick
(* current ● in-memory 💾 persisted)
*currently active●in-memory (live SDK client)💾persisted (resumes Claude's full history on next use)
TELEGRAM_BOT_TOKEN=<from @BotFather>
ALLOWED_CHAT_IDS=<your chat id, comma-separated for multiple>
PROJECTS=teleop=C:\work\teleop,foo=C:\path\to\fooThe first PROJECTS entry is the default project on startup. .env entries take priority over projects.json and cannot be removed via /rmproj or teleop rm.
Projects added via /addproj or teleop add:
{
"myproj": "C:\\path\\to\\myproj"
}Persisted after the first reply in each session:
{
"8285174078": {
"teleop": {
"main": { "id": "33ecb5f9-...", "model": null },
"debug": { "id": "abcd1234-...", "model": "haiku" }
}
}
}After bridge restart, /session main will reconnect via the SDK's resume="33ecb5f9-..." option.
- Chat-ID whitelist: every command except
/idrequireschat_id ∈ ALLOWED_CHAT_IDS. - Dangerous-tool gate:
Bash/Write/Edit/NotebookEditroute throughcan_use_toolto the chat; user must reply/yes <token>within 5 minutes or the call is denied. - Read-only tools pass through:
Read,Glob,Grep, etc. - Random tokens: 6 hex characters, regenerated per tool call.
Threat model assumes a single-user, trusted dev machine. The bridge runs Claude Code on that machine with your privileges — effectively as you. Don't host this on untrusted hardware, don't share your Bot token.
.
├── bridge.py # single-file bridge
├── pyproject.toml # uv-managed metadata + deps
├── uv.lock
├── .env.example
├── sessions.json # auto-generated
├── projects.json # auto-generated
├── LICENSE
└── README.md
Startup hangs on getMe ConnectTimeout
Your proxy is timing out reaching api.telegram.org. Switch nodes or reconnect the VPN and try again.
Bot doesn't respond
- Check the log for
Application started. - Check for
unauthorized chat=xxx— the chat is not in the whitelist.
/sessions shows ○ 💾 main but no history after a message
SDK resume occasionally fails; the bridge automatically falls back to a new session and clears the stale entry from sessions.json. You'll see resume failed for ..., falling back to new session in the log.
teleop command not found
After uv tool install --editable ., run uv tool update-shell and reopen the terminal. Already-open shells don't pick up the new PATH.
- Inline-keyboard buttons instead of
/yes/no(better for voice) -
/import <session-id>to attach a Claude Code IDE conversation to the bot - TTS replies (drive / commute-friendly)
- Verified on Linux / macOS (currently developed on Windows 11)
MIT © 2026 Weishuai Song