@gonzih/cc-tg 0.2.8 → 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 CHANGED
@@ -1,6 +1,8 @@
1
1
  # cc-tg
2
2
 
3
- Claude Code Telegram bot. Chat with Claude Code from Telegram — voice messages, scheduled prompts, and automatic file delivery.
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 CLAUDE_CODE_TOKEN=your_claude_token npx @gonzih/cc-tg
14
+ TELEGRAM_BOT_TOKEN=your_bot_token CLAUDE_CODE_OAUTH_TOKEN=your_claude_token npx @gonzih/cc-tg
13
15
  ```
14
16
 
15
- That's it. Open your bot in Telegram and start chatting.
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
- | `CLAUDE_CODE_TOKEN` | yes* | Claude Code OAuth token (starts with `sk-ant-oat`) |
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 `CLAUDE_CODE_TOKEN` or `ANTHROPIC_API_KEY` is required.
28
-
29
- ## How to get your Claude Code token
29
+ *One of `CLAUDE_CODE_OAUTH_TOKEN` or `ANTHROPIC_API_KEY` required.
30
30
 
31
- Run this once to generate a long-lived OAuth token:
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
- It opens a browser, logs you in with your Anthropic account, and prints a token starting with `sk-ant-oat`. Paste that as `CLAUDE_CODE_TOKEN`.
37
+ Opens a browser, logs in with your Anthropic account, prints a token starting with `sk-ant-oat`.
38
38
 
39
- ## How to get your Telegram user ID
39
+ ## Get your Telegram user ID
40
40
 
41
- Message [@userinfobot](https://t.me/userinfobot) on Telegram — it replies with your numeric ID.
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 (base64 content block) |
57
- | Document / file | Downloaded to `<CWD>/.cc-tg/uploads/`, path passed to Claude as `ATTACHMENTS: [name](path)` |
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 within a conversation. `/reset` starts a fresh session.
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 → automatically transcribed via whisper.cpp → fed into Claude as text. Requires `whisper-cpp` and `ffmpeg` installed on the host.
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 → downloaded and base64-encoded → sent to Claude as a native image content block via the stream-JSON protocol. Claude sees the full image, no intermediate vision step. Caption (if any) is included as text alongside the image.
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 as a document → 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.
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. Hybrid detection: tracks `Write`/`Edit` tool calls during the session, cross-references with filenames mentioned in the final response.
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 that fire into your Claude session on a timer:
83
+ Schedule recurring prompts on a timer:
78
84
 
79
85
  ```
80
- /cron every 1h check whale-watcher logs and summarize any new large trades
81
- /cron every 6h run the market scan and save results to daily-report.md
82
- /cron every 30m ping the API and alert me if anything looks off
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
- Cron jobs persist to `<CWD>/.cc-tg/crons.json` and are restored on bot restart. Output is prefixed with `CRON: <prompt>` so you know what triggered it. Files written by cron jobs are uploaded the same way as regular responses.
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
- ### Typing indicator
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
- ### Permissions
91
- Runs Claude Code with `--dangerously-skip-permissions` no confirmation prompts blocking headless execution.
100
+ ### MCP management commands
101
+ Manage the cc-agent MCP server from Telegram without SSH:
92
102
 
93
- ## How it works
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
- Spawns a `claude` CLI subprocess per chat session using the stream-JSON protocol (same mechanism as the [ce_ce](https://github.com/ityonemo/ce_ce) Elixir library). Prompts pipe in via stdin, streaming JSON responses parse out. Only the final `result` message is forwarded to Telegram — no duplicate streaming chunks.
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>CLAUDE_CODE_TOKEN</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=CLAUDE_CODE_TOKEN=yyy
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 child = spawn(process.execPath, process.argv.slice(1), {
620
- detached: true,
621
- stdio: "inherit",
622
- env: process.env,
623
- });
624
- child.unref();
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) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gonzih/cc-tg",
3
- "version": "0.2.8",
3
+ "version": "0.2.10",
4
4
  "description": "Claude Code Telegram bot — chat with Claude Code via Telegram",
5
5
  "type": "module",
6
6
  "bin": {