@gonzih/cc-tg 0.2.9 → 0.2.10
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/README.md +57 -34
- package/dist/bot.js +11 -6
- package/dist/index.js +26 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# cc-tg
|
|
2
2
|
|
|
3
|
-
Claude Code Telegram bot. Chat with Claude Code from Telegram — voice
|
|
3
|
+
Claude Code Telegram bot. Chat with Claude Code from Telegram — text, voice, images, files, scheduled prompts, and bot management commands.
|
|
4
|
+
|
|
5
|
+
Built by [@Gonzih](https://github.com/Gonzih).
|
|
4
6
|
|
|
5
7
|
## Quickstart
|
|
6
8
|
|
|
@@ -9,90 +11,107 @@ Claude Code Telegram bot. Chat with Claude Code from Telegram — voice messages
|
|
|
9
11
|
**Step 2** — run:
|
|
10
12
|
|
|
11
13
|
```bash
|
|
12
|
-
TELEGRAM_BOT_TOKEN=your_bot_token
|
|
14
|
+
TELEGRAM_BOT_TOKEN=your_bot_token CLAUDE_CODE_OAUTH_TOKEN=your_claude_token npx @gonzih/cc-tg
|
|
13
15
|
```
|
|
14
16
|
|
|
15
|
-
|
|
17
|
+
Open your bot in Telegram and start chatting.
|
|
16
18
|
|
|
17
19
|
## Environment variables
|
|
18
20
|
|
|
19
21
|
| Variable | Required | Description |
|
|
20
|
-
|
|
22
|
+
|----------|----------|-------------|
|
|
21
23
|
| `TELEGRAM_BOT_TOKEN` | yes | From @BotFather |
|
|
22
|
-
| `
|
|
24
|
+
| `CLAUDE_CODE_OAUTH_TOKEN` | yes* | Claude Code OAuth token (starts with `sk-ant-oat`) |
|
|
23
25
|
| `ANTHROPIC_API_KEY` | yes* | Alternative — API key from console.anthropic.com |
|
|
24
26
|
| `ALLOWED_USER_IDS` | no | Comma-separated Telegram user IDs. Leave empty to allow anyone |
|
|
25
27
|
| `CWD` | no | Working directory for Claude Code. Defaults to current directory |
|
|
26
28
|
|
|
27
|
-
*One of `
|
|
28
|
-
|
|
29
|
-
## How to get your Claude Code token
|
|
29
|
+
*One of `CLAUDE_CODE_OAUTH_TOKEN` or `ANTHROPIC_API_KEY` required.
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
## Get your Claude Code token
|
|
32
32
|
|
|
33
33
|
```bash
|
|
34
34
|
npx @anthropic-ai/claude-code setup-token
|
|
35
35
|
```
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
Opens a browser, logs in with your Anthropic account, prints a token starting with `sk-ant-oat`.
|
|
38
38
|
|
|
39
|
-
##
|
|
39
|
+
## Get your Telegram user ID
|
|
40
40
|
|
|
41
|
-
Message [@userinfobot](https://t.me/userinfobot)
|
|
41
|
+
Message [@userinfobot](https://t.me/userinfobot) — it replies with your numeric ID.
|
|
42
42
|
|
|
43
43
|
## Bot commands
|
|
44
44
|
|
|
45
45
|
| Command | Action |
|
|
46
|
-
|
|
46
|
+
|---------|--------|
|
|
47
47
|
| `/start` or `/reset` | Kill current Claude session and start fresh |
|
|
48
48
|
| `/stop` | Interrupt the running Claude task |
|
|
49
49
|
| `/status` | Check if a session is active |
|
|
50
|
+
| `/help` | Show all available commands |
|
|
50
51
|
| `/cron every 1h <prompt>` | Schedule a recurring prompt |
|
|
51
|
-
| `/cron list` | Show active cron jobs |
|
|
52
|
+
| `/cron list` | Show active cron jobs (numbered) |
|
|
53
|
+
| `/cron edit <#> [schedule/prompt] <value>` | Edit a cron job in place |
|
|
52
54
|
| `/cron remove <id>` | Remove a specific cron job |
|
|
53
55
|
| `/cron clear` | Remove all cron jobs |
|
|
56
|
+
| `/reload_mcp` | Reload cc-agent MCP server without dropping your Claude session |
|
|
57
|
+
| `/mcp_version` | Show latest published cc-agent npm version and current cache |
|
|
58
|
+
| `/clear_npx_cache` | Clear npx cache and reload cc-agent (upgrades to latest version) |
|
|
59
|
+
| `/restart` | Self-restart the cc-tg bot process (no SSH needed) |
|
|
54
60
|
| Any text | Sent directly to Claude Code |
|
|
55
61
|
| Voice message | Transcribed via whisper.cpp and sent to Claude |
|
|
56
|
-
| Photo | Sent as native image input to Claude
|
|
57
|
-
| Document / file | Downloaded to `<CWD>/.cc-tg/uploads/`, path passed to Claude
|
|
62
|
+
| Photo | Sent as native image input to Claude |
|
|
63
|
+
| Document / file | Downloaded to `<CWD>/.cc-tg/uploads/`, path passed to Claude |
|
|
58
64
|
|
|
59
65
|
## Features
|
|
60
66
|
|
|
61
67
|
### Persistent sessions
|
|
62
|
-
Each Telegram chat ID gets its own isolated Claude Code subprocess. Sessions survive between messages — Claude remembers context
|
|
68
|
+
Each Telegram chat ID gets its own isolated Claude Code subprocess. Sessions survive between messages — Claude remembers context. `/reset` starts fresh.
|
|
63
69
|
|
|
64
70
|
### Voice messages
|
|
65
|
-
Send a voice message →
|
|
71
|
+
Send a voice message → transcribed via whisper.cpp → fed to Claude as text. Requires `whisper-cpp` and `ffmpeg` on the host.
|
|
66
72
|
|
|
67
73
|
### Images
|
|
68
|
-
Send a photo →
|
|
74
|
+
Send a photo → base64-encoded → sent to Claude as a native image content block. Claude sees the full image. Caption included as text.
|
|
69
75
|
|
|
70
76
|
### Documents
|
|
71
|
-
Send any file
|
|
77
|
+
Send any file → downloaded to `<CWD>/.cc-tg/uploads/<filename>` → Claude receives the path as `ATTACHMENTS: [filename](path)` and can read/process it directly. Works for PDFs, CSVs, code files, etc.
|
|
72
78
|
|
|
73
79
|
### File delivery
|
|
74
|
-
When Claude writes a file and mentions it in the response, the bot automatically uploads it to Telegram.
|
|
80
|
+
When Claude writes a file and mentions it in the response, the bot automatically uploads it to Telegram. Tracks `Write`/`Edit` tool calls during the session, cross-references with filenames in the final response.
|
|
75
81
|
|
|
76
82
|
### Cron jobs
|
|
77
|
-
Schedule recurring prompts
|
|
83
|
+
Schedule recurring prompts on a timer:
|
|
78
84
|
|
|
79
85
|
```
|
|
80
|
-
/cron every 1h check
|
|
81
|
-
/cron every 6h run
|
|
82
|
-
/cron every 30m ping the API and alert
|
|
86
|
+
/cron every 1h check logs and summarize new alerts
|
|
87
|
+
/cron every 6h run market scan and save to daily-report.md
|
|
88
|
+
/cron every 30m ping the API and alert if anything looks off
|
|
83
89
|
```
|
|
84
90
|
|
|
85
|
-
|
|
91
|
+
Edit without removing and re-adding:
|
|
92
|
+
```
|
|
93
|
+
/cron edit 1 every 2h updated task description
|
|
94
|
+
/cron edit 1 schedule every 4h
|
|
95
|
+
/cron edit 1 prompt new task text only
|
|
96
|
+
```
|
|
86
97
|
|
|
87
|
-
|
|
88
|
-
While Claude is working, the bot sends a continuous typing indicator so you know it's active.
|
|
98
|
+
Cron jobs persist to `<CWD>/.cc-tg/crons.json` and restore on restart. Output is prefixed with `CRON: <prompt>`. Files written by cron jobs are uploaded automatically.
|
|
89
99
|
|
|
90
|
-
###
|
|
91
|
-
|
|
100
|
+
### MCP management commands
|
|
101
|
+
Manage the cc-agent MCP server from Telegram without SSH:
|
|
92
102
|
|
|
93
|
-
|
|
103
|
+
- `/reload_mcp` — sends SIGTERM to the cc-agent process; Claude Code auto-restarts it on next tool call. Useful after updating cc-agent config.
|
|
104
|
+
- `/mcp_version` — shows the latest `@gonzih/cc-agent` version on npm and what's in your local npx cache.
|
|
105
|
+
- `/clear_npx_cache` — deletes `~/.npm/_npx/` and kills cc-agent, forcing a fresh download of the latest version on next use.
|
|
94
106
|
|
|
95
|
-
|
|
107
|
+
### Self-restart
|
|
108
|
+
`/restart` — spawns a detached child process with the same Node binary and args, sends you a confirmation message, then exits. The new process inherits all environment variables. No SSH required to restart the bot after updates.
|
|
109
|
+
|
|
110
|
+
### Typing indicator
|
|
111
|
+
While Claude is working, the bot sends a continuous typing indicator. Works for both regular messages and cron job execution.
|
|
112
|
+
|
|
113
|
+
### Bot command menu
|
|
114
|
+
All commands are registered with Telegram's `/` menu via `setMyCommands` on startup — no need to remember commands.
|
|
96
115
|
|
|
97
116
|
## Run persistently
|
|
98
117
|
|
|
@@ -115,7 +134,7 @@ Spawns a `claude` CLI subprocess per chat session using the stream-JSON protocol
|
|
|
115
134
|
<dict>
|
|
116
135
|
<key>TELEGRAM_BOT_TOKEN</key>
|
|
117
136
|
<string>your_token</string>
|
|
118
|
-
<key>
|
|
137
|
+
<key>CLAUDE_CODE_OAUTH_TOKEN</key>
|
|
119
138
|
<string>your_claude_token</string>
|
|
120
139
|
<key>ALLOWED_USER_IDS</key>
|
|
121
140
|
<string>your_telegram_id</string>
|
|
@@ -152,7 +171,7 @@ Description=cc-tg Claude Code Telegram bot
|
|
|
152
171
|
|
|
153
172
|
[Service]
|
|
154
173
|
Environment=TELEGRAM_BOT_TOKEN=xxx
|
|
155
|
-
Environment=
|
|
174
|
+
Environment=CLAUDE_CODE_OAUTH_TOKEN=yyy
|
|
156
175
|
Environment=ALLOWED_USER_IDS=123456789
|
|
157
176
|
Environment=CWD=/home/you/your-project
|
|
158
177
|
WorkingDirectory=/home/you/your-project
|
|
@@ -168,3 +187,7 @@ WantedBy=multi-user.target
|
|
|
168
187
|
- Node.js 18+
|
|
169
188
|
- `claude` CLI: `npm install -g @anthropic-ai/claude-code`
|
|
170
189
|
- Voice transcription (optional): `whisper-cpp` + `ffmpeg`
|
|
190
|
+
|
|
191
|
+
## Related
|
|
192
|
+
|
|
193
|
+
- [cc-agent](https://github.com/Gonzih/cc-agent) — MCP server for spawning Claude Code subagents by [@Gonzih](https://github.com/Gonzih)
|
package/dist/bot.js
CHANGED
|
@@ -616,12 +616,17 @@ export class CcTgBot {
|
|
|
616
616
|
await this.bot.sendMessage(chatId, "Restarting bot... brb.");
|
|
617
617
|
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
618
618
|
this.stop();
|
|
619
|
-
const
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
619
|
+
const isLaunchd = process.ppid === 1;
|
|
620
|
+
if (!isLaunchd) {
|
|
621
|
+
// Running manually — spawn a replacement process
|
|
622
|
+
const child = spawn(process.execPath, process.argv.slice(1), {
|
|
623
|
+
detached: true,
|
|
624
|
+
stdio: "ignore",
|
|
625
|
+
env: process.env,
|
|
626
|
+
});
|
|
627
|
+
child.unref();
|
|
628
|
+
}
|
|
629
|
+
// If launchd-managed, just exit — launchd will restart us
|
|
625
630
|
process.exit(0);
|
|
626
631
|
}
|
|
627
632
|
killSession(chatId, keepCrons = true) {
|
package/dist/index.js
CHANGED
|
@@ -13,7 +13,33 @@
|
|
|
13
13
|
* ALLOWED_USER_IDS — comma-separated Telegram user IDs (leave empty to allow all)
|
|
14
14
|
* CWD — working directory for Claude Code (default: process.cwd())
|
|
15
15
|
*/
|
|
16
|
+
import { existsSync, writeFileSync, unlinkSync, readFileSync } from "fs";
|
|
17
|
+
import { tmpdir } from "os";
|
|
18
|
+
import { join } from "path";
|
|
16
19
|
import { CcTgBot } from "./bot.js";
|
|
20
|
+
const LOCK_FILE = join(tmpdir(), "cc-tg.lock");
|
|
21
|
+
function acquireLock() {
|
|
22
|
+
if (existsSync(LOCK_FILE)) {
|
|
23
|
+
try {
|
|
24
|
+
const pid = parseInt(readFileSync(LOCK_FILE, "utf8").trim());
|
|
25
|
+
process.kill(pid, 0);
|
|
26
|
+
console.error(`[cc-tg] Another instance is already running (PID ${pid}). Exiting.`);
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
// PID is dead — stale lock, take over
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
writeFileSync(LOCK_FILE, String(process.pid));
|
|
34
|
+
process.on("exit", () => { try {
|
|
35
|
+
unlinkSync(LOCK_FILE);
|
|
36
|
+
}
|
|
37
|
+
catch { } });
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
if (!acquireLock()) {
|
|
41
|
+
process.exit(1);
|
|
42
|
+
}
|
|
17
43
|
function required(name) {
|
|
18
44
|
const val = process.env[name];
|
|
19
45
|
if (!val) {
|