claude-telegram-bot 0.3.36 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +326 -0
- package/README.ko.md +95 -25
- package/README.md +108 -31
- package/bot.mjs +456 -58
- package/config.example.json +11 -1
- package/ctb.mjs +84 -29
- package/package.json +5 -2
package/README.md
CHANGED
|
@@ -6,19 +6,26 @@
|
|
|
6
6
|
[](https://www.npmjs.com/package/claude-telegram-bot)
|
|
7
7
|
[](https://opensource.org/licenses/MIT)
|
|
8
8
|
|
|
9
|
-
Use Claude Code from Telegram — run
|
|
9
|
+
Use Claude Code or Codex from Telegram — run coding agents anywhere, from any device.
|
|
10
10
|
|
|
11
|
-
**A zero-dependency,
|
|
11
|
+
**A zero-dependency, daemonized Telegram bridge for Claude Code and Codex — no Bun, no Python, no open session.**
|
|
12
12
|
|
|
13
|
-
A
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
A small bridge that takes your Telegram messages, runs the selected coding provider in a project
|
|
14
|
+
folder, and sends the result back to the chat. It uses only Node 18+ built-ins, with no runtime
|
|
15
|
+
dependencies to install.
|
|
16
16
|
|
|
17
|
-
```
|
|
18
|
-
[you] → Telegram → bot.mjs
|
|
17
|
+
```text
|
|
18
|
+
[you] → Telegram → bot.mjs
|
|
19
|
+
├─ Claude provider → state.sessionId
|
|
20
|
+
├─ Codex provider → state.codexSessionId
|
|
21
|
+
└─ Ollama mode/fallback
|
|
22
|
+
↓
|
|
23
|
+
result → Telegram
|
|
24
|
+
|
|
25
|
+
Claude limit → Codex fallback → codex-handoff.md → next Claude call
|
|
19
26
|
```
|
|
20
27
|
|
|
21
|
-
Drive
|
|
28
|
+
Drive a coding agent from your phone: run tests, edit files, commit, push — all from a chat.
|
|
22
29
|
It runs as a **background daemon** (launchd), so there's no interactive session to keep open.
|
|
23
30
|
|
|
24
31
|
> ### ⚠️ This is a remote code-execution tool by design. Read the [Security](#security) section before running it.
|
|
@@ -32,7 +39,9 @@ It runs as a **background daemon** (launchd), so there's no interactive session
|
|
|
32
39
|
- **Multi-persona** — split the *same* project into role-based bots (e.g. Developer + Planner)
|
|
33
40
|
with per-bot system prompts and **differentiated permission levels**.
|
|
34
41
|
- **Session continuity** — conversations resume across restarts (`--resume`); `/new` to reset.
|
|
35
|
-
- **
|
|
42
|
+
- **Provider switching** — use Claude or Codex as the main agent and switch with `/provider`.
|
|
43
|
+
- **Fallback handoff** — Codex can take over when Claude hits a limit and leave handoff notes.
|
|
44
|
+
- **Attachments** — send photos/docs/voice/video; they're saved locally and handed to the active provider.
|
|
36
45
|
- **Always-on** — ships with a launchd template for macOS (auto-start, auto-restart).
|
|
37
46
|
|
|
38
47
|
## How it compares
|
|
@@ -43,12 +52,12 @@ can pick the right tool:
|
|
|
43
52
|
| | This bot | [Official Claude Code Channels](https://code.claude.com/docs/en/channels) | [claude-code-telegram](https://github.com/RichardAtCT/claude-code-telegram) |
|
|
44
53
|
|---|---|---|---|
|
|
45
54
|
| Runtime | **Node built-ins only** | Bun + MCP plugin | Python 3.11+ + libs |
|
|
46
|
-
| Execution model | headless
|
|
55
|
+
| Execution model | headless Claude or Codex process per message | events pushed into an **open** `claude --channels` session | Claude SDK / CLI |
|
|
47
56
|
| Stays running as | **background daemon** (no session open) | a live interactive session you keep running | service / daemon |
|
|
48
57
|
| Multi-persona, permission-scoped bots on one repo | **yes** (dev=`bypass`, planner=`plan`) | no | no |
|
|
49
58
|
| Per-action permission approval (inline buttons) | no (set `permissionMode`) | **yes** | partial |
|
|
50
59
|
| Feature breadth (webhooks, cron, voice, export) | minimal | medium | **large** |
|
|
51
|
-
|
|
|
60
|
+
| Runtime dependencies | **none (Node built-ins)** | plugin runtime | Python packages |
|
|
52
61
|
|
|
53
62
|
**Use the official Channels** if you want per-action approvals and don't mind keeping a session
|
|
54
63
|
open. **Use claude-code-telegram** if you want maximum features. **Use this** if you want a
|
|
@@ -82,12 +91,16 @@ to execute commands; that power is the point, and also the risk. Read this befor
|
|
|
82
91
|
- **Guard the token like a credential.** `config.json` and `state.json` are in `.gitignore` so you
|
|
83
92
|
don't commit it — keep it that way. Never paste the token into issues, logs, or screenshots. The
|
|
84
93
|
startup log redacts it (`token: <redacted>`); don't add it back.
|
|
85
|
-
- **
|
|
86
|
-
|
|
94
|
+
- **The bot itself is not a security boundary.** Provider controls reduce risk but do not isolate
|
|
95
|
+
Telegram, custom commands, or the daemon process. Claude runs with `permissionMode`; Codex uses
|
|
96
|
+
`codexSandbox`. Both processes still inherit the daemon user's environment and credentials.
|
|
87
97
|
|
|
88
98
|
### Choose the least permission you can live with
|
|
89
99
|
|
|
90
|
-
|
|
100
|
+
Claude and Codex use different safety controls. Switching provider can therefore change the
|
|
101
|
+
effective permission boundary.
|
|
102
|
+
|
|
103
|
+
For Claude, `permissionMode` is the main safety dial:
|
|
91
104
|
|
|
92
105
|
| Mode | What it allows | Use when |
|
|
93
106
|
|---|---|---|
|
|
@@ -101,6 +114,10 @@ Practical hardening:
|
|
|
101
114
|
- Point `projectDir` at a **specific project**, not your home directory — limit the blast radius.
|
|
102
115
|
- For multi-persona setups, give only **one** bot `bypassPermissions`; keep the rest on `plan`.
|
|
103
116
|
- Consider running on a dedicated user account or VM if you'll leave it always-on.
|
|
117
|
+
- For Codex, keep `codexSandbox: "workspace-write"` unless you understand the implications of a
|
|
118
|
+
broader sandbox setting. `/plan`, `/compact`, and automatic compact are currently Claude-only.
|
|
119
|
+
- Custom `/commands` run directly as the daemon user; neither `permissionMode` nor `codexSandbox`
|
|
120
|
+
restricts them.
|
|
104
121
|
|
|
105
122
|
### Reporting a vulnerability
|
|
106
123
|
|
|
@@ -115,7 +132,9 @@ This is a standalone CLI/daemon, **not a library** — you don't `import` it. In
|
|
|
115
132
|
run via `npx`), point a config file at any project, and run it. `projectDir` in the config decides
|
|
116
133
|
which folder Claude works in, independent of where the bot is installed.
|
|
117
134
|
|
|
118
|
-
Prerequisites: **Node 18
|
|
135
|
+
Prerequisites: **Node 18+**, a Telegram bot token, and at least one configured provider. Install and
|
|
136
|
+
authenticate the **Claude CLI** for Claude, the **Codex CLI** for Codex or Codex fallback, and
|
|
137
|
+
**Ollama plus a local model** only if you enable Ollama mode/fallback.
|
|
119
138
|
|
|
120
139
|
**Option A — npx (no install)**
|
|
121
140
|
|
|
@@ -162,7 +181,22 @@ auth layer.)
|
|
|
162
181
|
- `run the solver tests and commit + push if they pass`
|
|
163
182
|
- `add an edge case to solve-2nd-floor-edges.ts`
|
|
164
183
|
|
|
165
|
-
|
|
184
|
+
Core commands:
|
|
185
|
+
|
|
186
|
+
| Command | Purpose |
|
|
187
|
+
|---|---|
|
|
188
|
+
| `/provider [claude\|codex\|default]` | View or switch the Telegram bot's provider override |
|
|
189
|
+
| `/model [name\|default]` | View or switch the active provider's model |
|
|
190
|
+
| `/new` | Reset the active provider's conversation session |
|
|
191
|
+
| `/plan <request>` | Produce a plan and wait for approval (Claude only) |
|
|
192
|
+
| `/compact` | Compact the current context (Claude only) |
|
|
193
|
+
| `/stop [--reset]` | Stop the task; optionally restore its previous session ID |
|
|
194
|
+
| `/ollama` | Toggle local Ollama chat mode |
|
|
195
|
+
| `/testfallback` | Test the configured Codex or Ollama fallback |
|
|
196
|
+
| `/status` | Show version, provider, CLI versions, model, fallback, and session state |
|
|
197
|
+
| `/remember <text>` · `/memory` | Save or inspect persistent memory |
|
|
198
|
+
| `/cron` · `/reserve` | Manage scheduled jobs and usage-limit retries |
|
|
199
|
+
| `/autocompact` · `/restart` · `/id` · `/help` | Maintenance and help commands |
|
|
166
200
|
|
|
167
201
|
> **`/plan <request>`** runs the request in read-only plan mode (no edits, no shell) regardless of
|
|
168
202
|
> the bot's configured `permissionMode`, and replies with the plan plus **✅ Proceed / ❌ Cancel**
|
|
@@ -171,7 +205,7 @@ Commands: `/new` (reset context / new session) · `/compact` (compress context,
|
|
|
171
205
|
> you a review step before a `bypassPermissions` bot touches anything. The pending approval expires
|
|
172
206
|
> if you start a new session with `/new` first.
|
|
173
207
|
|
|
174
|
-
> **`/stop`** kills the running
|
|
208
|
+
> **`/stop`** kills the running provider process immediately and clears any queued messages.
|
|
175
209
|
> Add `--reset` to also restore the session to the state it was in *before* the task started,
|
|
176
210
|
> so the conversation history doesn't include the interrupted work.
|
|
177
211
|
|
|
@@ -188,6 +222,22 @@ Commands: `/new` (reset context / new session) · `/compact` (compress context,
|
|
|
188
222
|
|
|
189
223
|
---
|
|
190
224
|
|
|
225
|
+
## Compatibility
|
|
226
|
+
|
|
227
|
+
The bot depends on CLI flags and machine-readable output that may change between releases. These are
|
|
228
|
+
the development-environment versions recorded as the compatibility baseline on 2026-07-10; they are
|
|
229
|
+
reference versions, not strict pins or a claim that every path passes. Use `/status` to see the
|
|
230
|
+
versions actually installed on the bot host.
|
|
231
|
+
|
|
232
|
+
| CLI | Recorded version | Relevant integration |
|
|
233
|
+
|---|---:|---|
|
|
234
|
+
| Claude Code | `2.1.206` | JSON output, session resume, permission mode |
|
|
235
|
+
| Codex CLI | `0.144.1` | `exec`, `exec resume`, JSONL events, workspace sandbox |
|
|
236
|
+
| Ollama | `0.31.1` | `ollama launch claude`, model selection, session handoff |
|
|
237
|
+
|
|
238
|
+
When upgrading one of these CLIs, run `/testfallback` and a normal Claude message before relying on
|
|
239
|
+
the bot unattended. Update this table after recording the new environment and checking those paths.
|
|
240
|
+
|
|
191
241
|
## Configuration
|
|
192
242
|
|
|
193
243
|
```sh
|
|
@@ -200,20 +250,44 @@ Edit `mybot.json`:
|
|
|
200
250
|
|---|---|
|
|
201
251
|
| `token` | Bot token from BotFather |
|
|
202
252
|
| `allowedChatId` | **Leave empty at first** → the bot tells you (step 3). Required before it runs anything. |
|
|
203
|
-
| `projectDir` | Absolute path to the working folder
|
|
253
|
+
| `projectDir` | Absolute path to the working folder the selected provider runs in |
|
|
254
|
+
| `provider` | (optional) Main provider for Telegram messages and scheduled jobs: `"claude"` (default) or `"codex"` |
|
|
204
255
|
| `claudeBin` | Output of `which claude` (absolute path recommended) |
|
|
205
|
-
| `permissionMode` | `plan` / `acceptEdits` / `bypassPermissions` — see [Security](#security) |
|
|
206
|
-
| `model` |
|
|
256
|
+
| `permissionMode` | Claude-only: `plan` / `acceptEdits` / `bypassPermissions` — see [Security](#security) |
|
|
257
|
+
| `model` | Claude model. Empty = CLI default. Override with `/model` while Claude is active. |
|
|
207
258
|
| `lang` | (optional) UI language. Empty = auto-detect per user (English default, Korean for Korean Telegram clients). Force with `"en"` / `"ko"`. |
|
|
208
259
|
| `name` | (optional) Bot name shown in `/help` — handy for telling multiple bots apart |
|
|
209
260
|
| `persona` | (optional) Role system prompt — defines a persona (developer/planner/…). See below |
|
|
210
261
|
| `appendSystemPrompt` | (optional) Override the default "be concise for Telegram" instruction |
|
|
211
|
-
| `env` | (optional) Extra environment variables passed to
|
|
262
|
+
| `env` | (optional) Extra environment variables passed to provider processes |
|
|
212
263
|
| `schedule` | (optional) Cron jobs that run a prompt on a timer — see [Scheduled tasks](#scheduled-tasks-cron) |
|
|
213
264
|
| `commands` | (optional) Custom `/commands` that run shell scripts — see [Custom commands](#custom-commands) |
|
|
214
|
-
| `
|
|
215
|
-
| `
|
|
216
|
-
| `
|
|
265
|
+
| `codexFallback` | (optional) `true` to enable Codex as the preferred fallback when Claude is rate-limited or out of credits |
|
|
266
|
+
| `codexBin` | (optional) Path to the `codex` binary. Defaults to `"codex"` on `PATH`; use an absolute path for launchd |
|
|
267
|
+
| `codexModel` | (optional) Codex model override passed with `--model` |
|
|
268
|
+
| `codexSandbox` | (optional) Codex sandbox for a new `codex exec` session (default: `"workspace-write"`) |
|
|
269
|
+
| `codexTimeout` | (optional) Milliseconds to wait for Codex before falling back to reserve/Ollama (default: `600000`) |
|
|
270
|
+
| `ollamaFallback` | (optional) `true` to enable Ollama as a secondary fallback when Claude is rate-limited or out of credits |
|
|
271
|
+
| `ollamaModel` | (optional) Ollama model to use for fallback (default: `"qwen3.5:4b"`). The context a session carries over is capped by this model's runtime context window (`num_ctx`), which Ollama defaults to ~4K regardless of the model's architectural max — too small for a long Claude session. Bake a larger window into a variant with a `Modelfile` (`FROM qwen3.5:4b` + `PARAMETER num_ctx 6144`, `ollama create qwen3.5:4b-ctx6k -f Modelfile`) and point this at it. Size it to your RAM — on an 8 GB machine ~6K is the safe ceiling; 32K swaps the machine to death. |
|
|
272
|
+
| `ollamaBin` | (optional) Path to the `ollama` binary. Auto-detected at `/opt/homebrew/bin/ollama`, `/usr/local/bin/ollama`, `/usr/bin/ollama`, falling back to `"ollama"` on `PATH` — set this explicitly if your install lives elsewhere, since a launchd-run bot doesn't inherit your shell's `PATH` |
|
|
273
|
+
| `ollamaTimeout` | (optional) Milliseconds to wait for an Ollama reply before giving up (default: `360000` — local models can be slow to cold-start) |
|
|
274
|
+
| `autoCompactThreshold` | (optional) Auto-compact context when cached input tokens exceed this value (default: `100000`). Set to `0` to disable. Override at runtime with `/autocompact` (persists in state). |
|
|
275
|
+
|
|
276
|
+
The same config also drives local interactive sessions. `ctb mybot.json` uses `config.provider`,
|
|
277
|
+
while an explicit flag overrides it for that invocation:
|
|
278
|
+
|
|
279
|
+
```sh
|
|
280
|
+
ctb mybot.json --provider claude
|
|
281
|
+
ctb mybot.json --provider codex
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
Claude resumes `state.sessionId`; Codex resumes `state.codexSessionId` with
|
|
285
|
+
`codex resume <session-id>`. The sessions remain separate. The `/plan` approval workflow currently
|
|
286
|
+
requires `provider: "claude"`; normal messages, attachments, and scheduled jobs support both.
|
|
287
|
+
|
|
288
|
+
`/provider` stores a Telegram-only override in state, survives bot restarts, and does not rewrite
|
|
289
|
+
the config. The local `ctb` command intentionally continues to use `config.provider` or its explicit
|
|
290
|
+
`--provider` flag.
|
|
217
291
|
|
|
218
292
|
State and downloaded attachments live in a hidden **`.claude-bot/`** folder next to the config
|
|
219
293
|
file, so projects stay isolated. Upgrading from an older version **auto-moves** an existing
|
|
@@ -231,14 +305,16 @@ your launchd plist points them.
|
|
|
231
305
|
- **Formatting**: the reply's Markdown (bold/code/headings/tables) is converted to Telegram-safe
|
|
232
306
|
HTML. If conversion ever produces invalid HTML, the message is automatically resent as plain text.
|
|
233
307
|
- **Attachments**: send a photo/document/voice/video and it's downloaded into `attachments/`; the
|
|
234
|
-
absolute path is handed to
|
|
235
|
-
- **Sessions**:
|
|
236
|
-
|
|
308
|
+
absolute path is handed to the active provider (caption included as the message).
|
|
309
|
+
- **Sessions**: Claude and Codex keep separate session IDs, so switching providers preserves both
|
|
310
|
+
conversations. `/new` resets only the active provider's session.
|
|
237
311
|
- **Message queue**: if you send a message while a task is running, it is queued (not dropped). When the task finishes, all queued messages are merged into a single prompt so Claude can resolve corrections and follow-ups in one pass (e.g. "do X" then "never mind, do Y" → handled together). Use `/stop` to cancel the running task and discard the queue.
|
|
238
312
|
- **Model hint**: the bot tells Claude which model it is running as. If Claude judges a question to be beyond its current tier, it appends a one-line suggestion at the end of the reply (e.g. 💡 `/model sonnet`). Switch with `/model <name>` — `haiku`, `sonnet`, `opus`, `fable`, or a full model id. The choice persists in `state.json` across restarts.
|
|
239
|
-
- **Usage-limit queue**: when a Claude Max / API rate-limit error includes a reset time, the triggering message is
|
|
240
|
-
- **
|
|
241
|
-
- **
|
|
313
|
+
- **Usage-limit queue**: when a Claude Max / API rate-limit error includes a reset time, the bot first tries enabled fallbacks. If no fallback is enabled or every fallback fails, the triggering message is queued and retried at that time — just like messages queued while Claude is busy. Any additional messages you send during the limit window are also added to the queue. Use `/reserve` to check queue status and reset time, `/reserve rm` to cancel and clear the queue.
|
|
314
|
+
- **Codex fallback**: set `"codexFallback": true` to run `codex exec` when Claude is rate-limited or out of credits. Codex keeps its own session in `state.codexSessionId` using `codex exec resume <id>`, but Claude and Codex sessions are not interoperable. Each successful Codex fallback appends a summary to `.claude-bot/codex-handoff.md`, and future Claude calls receive the recent handoff notes as context.
|
|
315
|
+
- **Runtime provider switching**: use `/provider` to view the active provider, `/provider claude` or `/provider codex` to store a bot-state override, and `/provider default` to return to the config value. Each provider's session is preserved separately.
|
|
316
|
+
- **Ollama fallback**: set `"ollamaFallback": true` and point `"ollamaModel"` at a locally-installed [Ollama](https://ollama.ai) model (default: `"qwen3.5:4b"`). Ollama is now a secondary automatic fallback when Codex is disabled or fails, and `/ollama` still toggles local chat mode manually. It runs Claude Code through the local model via `ollama launch claude … --resume <session>`, but this remains best-effort because local model context windows are much smaller than Claude's.
|
|
317
|
+
- **Auto-compact**: the bot tracks how many cached tokens are in the session context. When `cache_read_input_tokens` exceeds `autoCompactThreshold` (default 100 000), it automatically runs `/compact` and notifies you. Tune the threshold in config, or at runtime with `/autocompact <number>` (`/autocompact off` to disable, `/autocompact default` to reset) — the override persists in `state.json` across restarts. You can also run `/compact` manually at any time.
|
|
242
318
|
|
|
243
319
|
### Custom commands
|
|
244
320
|
|
|
@@ -431,8 +507,9 @@ launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.claudebot.example.pl
|
|
|
431
507
|
## Requirements
|
|
432
508
|
|
|
433
509
|
- Node.js 18+ (for built-in `fetch`)
|
|
434
|
-
- The `claude` CLI installed and authenticated on the host
|
|
435
510
|
- A Telegram bot token from `@BotFather`
|
|
511
|
+
- At least one provider: authenticated Claude CLI or authenticated Codex CLI
|
|
512
|
+
- Optional: Codex CLI for Codex fallback; Ollama and a downloaded model for Ollama mode/fallback
|
|
436
513
|
|
|
437
514
|
## License
|
|
438
515
|
|