claude-telegram-bot 0.1.0 → 0.2.1
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.ko.md +164 -215
- package/README.md +90 -20
- package/bot.mjs +0 -0
- package/config.example.json +9 -5
- package/package.json +1 -1
package/README.ko.md
CHANGED
|
@@ -1,306 +1,255 @@
|
|
|
1
|
-
# Claude Telegram Bot
|
|
1
|
+
# Claude Telegram Bot
|
|
2
2
|
|
|
3
3
|
**한국어** · [English](./README.md)
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
텔레그램 메시지를 받아 지정한 프로젝트 폴더에서 `claude -p`(헤드리스 모드)를 실행하고
|
|
8
|
-
결과를 다시 텔레그램으로 보내주는 작은 브릿지. `bot.mjs` 파일 하나, Node 18+ 내장 기능만 사용 —
|
|
9
|
-
`npm install`할 것도 없고, 감사(audit)할 거라곤 읽기 쉬운 ~400줄이 전부.
|
|
5
|
+
텔레그램으로 메시지를 보내면, 집이나 서버에 켜둔 Claude Code가 작업하고 결과를 다시 텔레그램으로 돌려주는 봇입니다.
|
|
10
6
|
|
|
11
7
|
```
|
|
12
|
-
[
|
|
8
|
+
[나] → 텔레그램 → bot.mjs → claude -p (작업 폴더) → 결과 → 텔레그램
|
|
13
9
|
```
|
|
14
10
|
|
|
15
|
-
|
|
16
|
-
**백그라운드 데몬**(launchd)으로 돌아서 인터랙티브 세션을 열어둘 필요가 없음.
|
|
11
|
+
## 왜 만들었나
|
|
17
12
|
|
|
18
|
-
|
|
19
|
-
> 텔레그램으로 보낸 메시지는 봇이 도는 머신에서 **명령으로 실행**됩니다.
|
|
20
|
-
> `permissionMode: bypassPermissions`면 한 줄짜리 메시지가 네 계정 권한으로 **무엇이든** 실행할 수 있습니다.
|
|
13
|
+
자리를 비운 사이에도 폰으로 빌드를 돌려보거나 간단한 수정을 맡기고 싶을 때가 있습니다. 그렇다고 외부에서 데스크톱에 원격 접속해서 터미널을 여는 건 번거롭죠.
|
|
21
14
|
|
|
22
|
-
|
|
15
|
+
텔레그램 봇이면 충분합니다. 메시지를 보내면 집(또는 개인 서버)의 `claude`가 헤드리스로 돌아 작업하고, 답을 채팅으로 보내줍니다. 별도 웹 대시보드도, 추가 서버도 없습니다. 파일 하나(`bot.mjs`)와 설정 파일 하나가 전부입니다.
|
|
23
16
|
|
|
24
|
-
|
|
17
|
+
## 이런 분께
|
|
25
18
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
| 상시 가동 형태 | **백그라운드 데몬** (세션 안 떠도 됨) | 계속 떠 있는 인터랙티브 세션 | 서비스 / 데몬 |
|
|
31
|
-
| 한 레포에 권한 차등 멀티 페르소나 | **가능** (개발자=`bypass`, 기획자=`plan`) | 불가 | 불가 |
|
|
32
|
-
| 작업별 권한 승인 (인라인 버튼) | 없음 (`permissionMode`로) | **있음** | 일부 |
|
|
33
|
-
| 기능 폭 (웹훅·cron·음성·export) | 최소 | 중간 | **큼** |
|
|
34
|
-
| 읽고/포크할 코드량 | **~400줄, 단일 파일** | 큼 | 큼 |
|
|
19
|
+
- 외출·이동 중에 폰으로 테스트나 빌드를 돌려보고 싶은 분
|
|
20
|
+
- 자리를 비운 사이 간단한 수정·커밋을 맡겨두고 싶은 분
|
|
21
|
+
- 맥미니나 홈서버에 띄워두고 어디서든 접속하고 싶은 분
|
|
22
|
+
- 거창한 셀프호스트 구성 없이 텔레그램만으로 끝내고 싶은 분
|
|
35
23
|
|
|
36
|
-
|
|
37
|
-
claude-code-telegram. **의존성 0·감사 가능·데몬**이 필요하거나, 특히 같은 프로젝트에 **권한이 다른
|
|
38
|
-
역할별 페르소나 봇**을 띄우고 싶다면 → 이 봇.
|
|
24
|
+
OpenClaw처럼 웹 UI까지 갖춘 구성을 써봤다면, 이 프로젝트는 그 반대편이라고 보면 됩니다. 대시보드도 데이터베이스도 없고, 이미 설치해 로그인해 둔 `claude` CLI를 그대로 불러 쓰는 게 전부입니다. 설정과 코드를 30초면 훑어볼 수 있습니다.
|
|
39
25
|
|
|
40
|
-
##
|
|
26
|
+
## 동작 방식
|
|
41
27
|
|
|
42
|
-
|
|
28
|
+
- 텔레그램 봇 API를 롱폴링으로 받습니다.
|
|
29
|
+
- 메시지가 오면 작업 폴더(`projectDir`)에서 `claude -p`(헤드리스 모드)를 실행합니다.
|
|
30
|
+
- 세션은 `--resume`으로 이어지므로, 봇을 재시작해도 대화 맥락이 유지됩니다.
|
|
31
|
+
- 의존성이 없습니다. Node 18+ 내장 기능(`fetch`, `child_process`)만 씁니다.
|
|
43
32
|
|
|
44
|
-
|
|
45
|
-
- 상태(`state.json`)·첨부(`attachments/`)는 **그 config 파일이 있는 폴더**에 저장돼 프로젝트끼리 안 섞임
|
|
46
|
-
- **주의**: 텔레그램은 토큰당 폴링 1개만 허용 → 프로젝트마다 **BotFather 토큰을 따로** 만들어야 동시 운영 가능
|
|
47
|
-
- 상시 가동은 `com.claudebot.example.plist`를 프로젝트별로 복사해 등록 (아래 launchd 섹션 참고)
|
|
33
|
+
## 다른 도구와 비교
|
|
48
34
|
|
|
49
|
-
|
|
50
|
-
```
|
|
51
|
-
~/projects/A/claudebot.config.json (토큰 A, projectDir=~/projects/A)
|
|
52
|
-
~/projects/B/claudebot.config.json (토큰 B, projectDir=~/projects/B)
|
|
53
|
-
node bot.mjs ~/projects/A/claudebot.config.json # 인스턴스 A
|
|
54
|
-
node bot.mjs ~/projects/B/claudebot.config.json # 인스턴스 B
|
|
55
|
-
```
|
|
35
|
+
이 분야에는 이미 여러 도구가 있고, Anthropic도 공식 기능을 내놨습니다. 용도에 맞게 고르시면 됩니다.
|
|
56
36
|
|
|
57
|
-
|
|
37
|
+
| | 이 봇 | [공식 Claude Code Channels](https://code.claude.com/docs/en/channels) | [claude-code-telegram](https://github.com/RichardAtCT/claude-code-telegram) |
|
|
38
|
+
|---|---|---|---|
|
|
39
|
+
| 런타임 | Node 내장만 | Bun + MCP 플러그인 | Python 3.11+ |
|
|
40
|
+
| 실행 모델 | 메시지마다 `claude -p` | 떠 있는 세션에 이벤트 push | Claude SDK / CLI |
|
|
41
|
+
| 상시 가동 | 백그라운드 데몬 | 인터랙티브 세션 유지 | 서비스 / 데몬 |
|
|
42
|
+
| 권한 차등 페르소나 | 가능 | 불가 | 불가 |
|
|
43
|
+
| 작업별 권한 승인 버튼 | 없음 | 있음 | 일부 |
|
|
44
|
+
| 기능 범위 | 최소 | 중간 | 많음 |
|
|
58
45
|
|
|
59
|
-
|
|
60
|
-
코드는 하나, **config 파일만 역할별로** 따로 둔다.
|
|
46
|
+
정리하면 이렇습니다.
|
|
61
47
|
|
|
62
|
-
-
|
|
63
|
-
|
|
64
|
-
-
|
|
65
|
-
하나로 제한**하면 동시 편집 충돌을 피할 수 있다. 읽기·계획만 시키려면 `plan`.
|
|
66
|
-
- **세션 분리**: `state` 파일은 config 이름에서 파생된다
|
|
67
|
-
(`config.json`→`state.json`, `dev.config.json`→`dev.config.state.json`). 같은 폴더에
|
|
68
|
-
config 여러 개를 둬도 봇끼리 맥락이 안 섞임.
|
|
69
|
-
- **봇마다 토큰 1개**: 각 봇은 BotFather에서 별도 토큰 발급 (`allowedChatId`는 동일해도 됨).
|
|
48
|
+
- 작업마다 승인 버튼이 필요하고 세션을 계속 띄워둬도 괜찮다면 → **공식 Channels**
|
|
49
|
+
- 웹훅, cron, 음성 등 기능이 많이 필요하다면 → **claude-code-telegram**
|
|
50
|
+
- 구성을 최대한 단순하게 가져가고 싶거나, 한 코드로 여러 페르소나 봇을 굴리고 싶다면 → **이 봇**
|
|
70
51
|
|
|
71
|
-
|
|
72
|
-
```
|
|
73
|
-
dev.config.json (permissionMode: bypassPermissions, persona: "시니어 개발자...")
|
|
74
|
-
planner.config.json (permissionMode: plan, persona: "기획자 겸 UX 담당...")
|
|
75
|
-
node bot.mjs dev.config.json
|
|
76
|
-
node bot.mjs planner.config.json
|
|
77
|
-
```
|
|
52
|
+
## 요구 사항
|
|
78
53
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
| 기획자 | `plan` (읽기·계획만) | 기능 제안·스펙·UX/디자인 방향 |
|
|
54
|
+
- Node.js 18 이상 (내장 `fetch` 사용)
|
|
55
|
+
- `claude` CLI 설치 및 로그인 (봇은 이 인증을 그대로 씁니다)
|
|
56
|
+
- 텔레그램 봇 토큰 ([@BotFather](https://t.me/BotFather)에서 발급)
|
|
83
57
|
|
|
84
|
-
|
|
85
|
-
> 경로를 다르게 등록한다 (아래 launchd 섹션 참고).
|
|
58
|
+
상시 가동 예시는 macOS의 launchd 기준입니다. 리눅스라면 systemd나 pm2로 같은 구성을 만들면 됩니다.
|
|
86
59
|
|
|
87
|
-
|
|
60
|
+
## 설치 & 실행
|
|
88
61
|
|
|
89
|
-
|
|
62
|
+
라이브러리가 아니라 단독으로 도는 CLI입니다. `import`해서 쓰는 게 아니라, 전역으로 설치하거나 `npx`로 실행합니다. 작업 폴더는 설정의 `projectDir`로 정하므로, 봇을 어디에 설치하든 상관없습니다.
|
|
90
63
|
|
|
91
|
-
**
|
|
64
|
+
**npx로 바로 실행**
|
|
92
65
|
|
|
93
|
-
**2) 설정 파일 생성**
|
|
94
66
|
```sh
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
# config.json
|
|
98
|
-
# permissionMode 는 이미 bypassPermissions 로 설정돼 있음
|
|
67
|
+
npx claude-telegram-bot init # 현재 폴더에 config.json 생성
|
|
68
|
+
# config.json 편집 (token, projectDir 등)
|
|
69
|
+
npx claude-telegram-bot # config.json 으로 실행
|
|
99
70
|
```
|
|
100
71
|
|
|
101
|
-
|
|
72
|
+
**전역 설치 (상시 가동에 권장)**
|
|
73
|
+
|
|
102
74
|
```sh
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
#
|
|
106
|
-
#
|
|
75
|
+
npm i -g claude-telegram-bot
|
|
76
|
+
|
|
77
|
+
claude-telegram-bot init ~/botconfigs/myproj # 해당 경로에 config.json 생성
|
|
78
|
+
# config.json 편집
|
|
79
|
+
claude-telegram-bot ~/botconfigs/myproj/config.json
|
|
107
80
|
```
|
|
108
81
|
|
|
109
|
-
|
|
110
|
-
- `cross 솔버 테스트 돌리고 통과하면 커밋 후 push 해줘`
|
|
111
|
-
- `solve-2nd-floor-edges.ts 에 엣지 케이스 추가해줘`
|
|
82
|
+
> **설정 파일은 git에 올리지 마세요.** config 파일에는 봇 토큰이 들어 있습니다. git 레포 안에 둔다면 `config.json`, `state*.json`, `attachments/`를 그 프로젝트의 `.gitignore`에 추가하세요. 이 레포는 해당 패턴을 이미 무시하므로 `claudebot.config.json` 같은 이름도 안전하지만, 다른 프로젝트는 직접 지정해야 합니다.
|
|
112
83
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.cube.claudebot.plist
|
|
117
|
-
tail -f bot.log
|
|
118
|
-
```
|
|
84
|
+
## 설정
|
|
85
|
+
|
|
86
|
+
`config.json`의 키는 다음과 같습니다.
|
|
119
87
|
|
|
120
|
-
|
|
88
|
+
| 키 | 설명 |
|
|
89
|
+
|---|---|
|
|
90
|
+
| `token` | BotFather에서 받은 봇 토큰 |
|
|
91
|
+
| `allowedChatId` | 처음엔 비워두세요. 봇이 chatId를 알려줍니다 (아래 첫 실행 참고) |
|
|
92
|
+
| `projectDir` | Claude가 작업할 폴더의 절대경로 |
|
|
93
|
+
| `claudeBin` | `which claude` 결과 (절대경로 권장) |
|
|
94
|
+
| `permissionMode` | `plan`(읽기·계획만) / `acceptEdits`(편집 자동 승인) / `bypassPermissions`(쉘 포함 전부 자동) |
|
|
95
|
+
| `model` | 비우면 기본 모델. `opus`, `sonnet` 등 |
|
|
96
|
+
| `lang` | (선택) UI 언어. 비우면 사용자별 자동 판별(기본 영어, 텔레그램이 한국어면 한국어). `"en"`/`"ko"`로 고정 가능 |
|
|
97
|
+
| `name` | (선택) `/help`에 표시되는 봇 이름. 여러 봇 구분용 |
|
|
98
|
+
| `persona` | (선택) 역할 시스템 프롬프트. 페르소나 봇 정의용 |
|
|
99
|
+
| `appendSystemPrompt` | (선택) 기본 "간결하게 답하기" 지침을 직접 덮어쓸 때 |
|
|
100
|
+
| `env` | (선택) `claude` 프로세스에 넘길 환경 변수 |
|
|
101
|
+
| `schedule` | (선택) 정해진 시각에 프롬프트를 실행하는 cron 작업 — [예약 작업](#예약-작업-cron) 참고 |
|
|
121
102
|
|
|
122
|
-
|
|
103
|
+
`state.json`과 첨부 파일(`attachments/`)은 config 파일과 같은 폴더에 저장됩니다. 그래서 config만 따로 두면 프로젝트끼리 섞이지 않습니다.
|
|
123
104
|
|
|
124
|
-
|
|
105
|
+
## 첫 실행
|
|
125
106
|
|
|
126
|
-
|
|
107
|
+
1. **봇 토큰 발급** — 텔레그램에서 [@BotFather](https://t.me/BotFather)에게 `/newbot`을 보내고, 이름과 username(`_bot`으로 끝나야 함)을 정하면 토큰을 줍니다. `config.json`의 `token`에 넣고 `allowedChatId`는 비워둡니다.
|
|
108
|
+
2. **chatId 확인 후 잠그기** — 봇을 실행하고 텔레그램에서 아무 메시지나 보내면, 봇이 이 채팅의 `chatId`를 답장합니다. 그 숫자를 `allowedChatId`에 넣고 재시작하면 나만 쓸 수 있습니다. ([보안](#보안) 참고 — 이게 유일한 인증 수단입니다.)
|
|
109
|
+
3. **사용** — 그냥 메시지를 보냅니다.
|
|
110
|
+
- `테스트 돌려보고 통과하면 커밋하고 push 해줘`
|
|
111
|
+
- `api.ts 에 에러 핸들링 추가해줘`
|
|
127
112
|
|
|
128
|
-
|
|
129
|
-
2. `/newbot` 입력 → 봇 이름과 username 지정 (username은 `_bot`으로 끝나야 함)
|
|
130
|
-
3. 받은 **토큰**을 복사 (예: `123456789:AAxxxxxxxx`)
|
|
113
|
+
명령어: `/new`(맥락 초기화) · `/cron`(예약 작업 보기·추가·삭제) · `/restart`(문법 검사 후 재시작) · `/id`(채팅 ID 확인) · `/help`(도움말)
|
|
131
114
|
|
|
132
|
-
|
|
115
|
+
> **`/restart`** 는 먼저 `bot.mjs` 에 `node --check` 를 돌려 **문법 오류가 있으면 재시작을 취소**합니다(잘못된 수정이 봇을 크래시 루프에 빠뜨리는 것 방지). 통과하면 프로세스를 종료하고, 다시 띄우는 건 프로세스 관리자에게 맡깁니다. [launchd 설정](#상시-실행-launchd)(`KeepAlive`)이면 바로 동작하고, 관리자 없이 `node bot.mjs` 로만 돌리면 그냥 멈춥니다. 재시작 후 대화 세션은 `state.json` 의 ID로 이어집니다.
|
|
133
116
|
|
|
134
|
-
|
|
135
|
-
cd tools/claude-telegram-bot
|
|
136
|
-
cp config.example.json config.json
|
|
137
|
-
```
|
|
117
|
+
## 사용 메모
|
|
138
118
|
|
|
139
|
-
`
|
|
119
|
+
- **세션 유지** — 대화는 `--resume`으로 자동으로 이어집니다. 마지막 세션 ID가 `state.json`에 저장되므로 봇을 재시작해도 맥락이 남습니다. 새로 시작하려면 `/new`.
|
|
120
|
+
- **간결한 답변** — 텔레그램에 맞게 짧게 답하도록 시스템 프롬프트가 기본으로 붙습니다. 바꾸려면 `appendSystemPrompt`에 직접 넣으세요 (빈 문자열이면 끔).
|
|
121
|
+
- **언어** — 봇 자체 문구(`/help`, 명령 메뉴, 상태 메시지)는 **기본 영어**, 텔레그램이 한국어인 사용자에겐 한국어로 나옵니다. `lang`(`"en"`/`"ko"`)으로 고정할 수 있습니다. Claude의 실제 답변은 **사용자가 쓴 언어**를 따라갑니다. `/` 명령 메뉴는 `setMyCommands`로 언어별 등록됩니다.
|
|
122
|
+
- **서식 변환** — 답변의 마크다운(굵게·코드·표 등)을 텔레그램 HTML로 바꿔 보냅니다. 변환이 깨지는 경우엔 평문으로 다시 보냅니다.
|
|
123
|
+
- **첨부 파일** — 사진·문서·음성·영상을 보내면 `attachments/`에 내려받고, 그 경로를 Claude에게 전달합니다(캡션도 함께). 이미지는 Read로 열어볼 수 있습니다.
|
|
140
124
|
|
|
141
|
-
|
|
142
|
-
|---|---|
|
|
143
|
-
| `token` | BotFather에서 받은 토큰 |
|
|
144
|
-
| `allowedChatId` | **비워두고 시작** → 봇이 알려줌 (아래 3단계) |
|
|
145
|
-
| `projectDir` | 작업 폴더 (기본값 그대로 두면 됨) |
|
|
146
|
-
| `claudeBin` | `which claude` 결과 (절대경로 권장) |
|
|
147
|
-
| `permissionMode` | `plan`(읽기·계획만) / `acceptEdits`(파일편집 자동승인) / `bypassPermissions`(전부 자동, 쉘 포함) |
|
|
148
|
-
| `model` | 비워두면 기본 모델. `opus` / `sonnet` 등 |
|
|
149
|
-
| `name` | (선택) `/help`에 표시되는 봇 이름 — 멀티 봇 구분용 |
|
|
150
|
-
| `persona` | (선택) 역할 시스템 프롬프트 — 페르소나(개발자/기획자 등) 정의. 자세히는 아래 페르소나 섹션 |
|
|
125
|
+
## 예약 작업 (cron)
|
|
151
126
|
|
|
152
|
-
|
|
127
|
+
config에 `schedule` 배열을 두면 정해진 시각에 프롬프트를 자동 실행합니다 — 아침 브리핑, 주기적 점검, 리마인더 등. 각 항목은 프롬프트를 실행하고 결과를 `allowedChatId`로 보냅니다.
|
|
153
128
|
|
|
154
|
-
```
|
|
155
|
-
|
|
129
|
+
```json
|
|
130
|
+
"schedule": [
|
|
131
|
+
{ "cron": "0 9 * * 1-5", "label": "아침 브리핑", "prompt": "오늘 처리할 이슈/할 일을 요약해줘" },
|
|
132
|
+
{ "cron": "*/30 * * * *", "prompt": "CI 상태 확인해서 빨간 게 있을 때만 알려줘" }
|
|
133
|
+
]
|
|
156
134
|
```
|
|
157
135
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
## 4. 사용
|
|
136
|
+
- **`cron`** — 표준 5필드 `분 시 일 월 요일` (예: `0 9 * * 1-5` = 평일 09:00). `*`, 목록(`1,3,5`), 범위(`1-5`), 스텝(`*/15`)을 지원합니다. 요일 `0`과 `7`은 둘 다 일요일. 시각은 **호스트의 로컬 시간대** 기준입니다. 외부 의존성 없이 파서가 `bot.mjs` 안에 들어 있습니다.
|
|
137
|
+
- **`prompt`**(필수) — Claude에게 보낼 메시지. **`label`**(선택) — 답장 푸터와 `/cron` 목록에 표시되는 짧은 이름.
|
|
138
|
+
- **새 세션** — 예약 작업은 **독립된 세션**으로 돌아가서 내 대화 맥락을 오염시키지 않습니다(`state.json`은 내 것 그대로). 단일 작업 락을 공유하므로, 발사 시점에 다른 작업이 진행 중이면 그 회차는 **건너뜁니다**(로그 남김).
|
|
162
139
|
|
|
163
|
-
|
|
140
|
+
**채팅에서 자연어로 추가하기**
|
|
164
141
|
|
|
165
|
-
|
|
166
|
-
|
|
142
|
+
```
|
|
143
|
+
/cron add 매일 아침 9시에 열린 이슈 요약해줘
|
|
144
|
+
```
|
|
167
145
|
|
|
168
|
-
|
|
169
|
-
- `/new` — 대화 맥락 초기화 (새 세션)
|
|
170
|
-
- `/id` — 채팅 ID 확인
|
|
171
|
-
- `/help` — 도움말
|
|
146
|
+
봇이 이 문장을 Claude에게 보내 cron 표현식으로 바꾸고, **해석한 내용을 되돌려 보여줍니다**(잘못 읽었으면 바로 확인 가능). 그리고 `state.json`에 저장하므로 **재시작이 필요 없습니다**. 동적 작업에는 번호가 붙고, 다음으로 관리합니다.
|
|
172
147
|
|
|
173
|
-
|
|
174
|
-
|
|
148
|
+
- `/cron` — 전체 목록 (config 작업은 `[config]`, 동적 작업은 `#번호`로 표시)
|
|
149
|
+
- `/cron add <자연어 요청>` — 예: `/cron add 30분마다 CI 빨간 거 있으면 알려줘`
|
|
150
|
+
- `/cron rm <번호>` — 동적 작업 삭제 (config 작업은 파일에서 수정)
|
|
175
151
|
|
|
176
|
-
|
|
152
|
+
config에 적은 작업은 바꾸려면 재시작이 필요하고, 채팅으로 추가한 작업만 즉시 반영됩니다.
|
|
177
153
|
|
|
178
|
-
|
|
179
|
-
지침을 바꾸려면 `config.json`의 `appendSystemPrompt`에 문자열을 넣으면 됨(빈 문자열이면 비활성).
|
|
180
|
-
- **서식**: 응답의 마크다운(굵게/코드/제목/표)을 텔레그램 HTML로 변환해 전송함.
|
|
181
|
-
변환이 실패하는 예외 케이스는 자동으로 평문으로 재전송됨.
|
|
182
|
-
- **파일 첨부**: 사진/문서/음성/영상을 보내면 `attachments/`에 내려받아 그 경로를
|
|
183
|
-
Claude에게 전달함(캡션은 메시지로 같이 전달). 이미지도 Read로 열어볼 수 있음.
|
|
154
|
+
## 여러 프로젝트 / 페르소나
|
|
184
155
|
|
|
185
|
-
|
|
156
|
+
코드는 프로젝트에 종속되지 않습니다. config 파일만 하나씩 더 만들면 여러 봇을 동시에 굴릴 수 있습니다.
|
|
186
157
|
|
|
187
|
-
|
|
158
|
+
```sh
|
|
159
|
+
claude-telegram-bot ~/projects/A/claudebot.config.json # 프로젝트 A
|
|
160
|
+
claude-telegram-bot ~/projects/B/claudebot.config.json # 프로젝트 B
|
|
161
|
+
```
|
|
188
162
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
| `node bot.mjs` | 종료됨 | ✗ | ✗ | 테스트·chatId 확인 |
|
|
192
|
-
| `nohup node bot.mjs > bot.log 2>&1 &` | 유지 | ✗ | ✗ | 임시 백그라운드 |
|
|
193
|
-
| **launchd (LaunchAgent)** | 유지 | ✅ 자동 시작 | ✅ 자동 재시작 | **상시 가동 (권장)** |
|
|
163
|
+
- 텔레그램은 토큰 하나당 폴링 하나만 허용합니다. 그래서 봇마다 BotFather 토큰을 따로 발급해야 합니다.
|
|
164
|
+
- `state`와 `attachments`는 config 옆에 저장되므로 봇끼리 섞이지 않습니다.
|
|
194
165
|
|
|
195
|
-
|
|
196
|
-
> 터미널을 닫아도 유지하려면 최소 `nohup`, 재부팅·크래시까지 견디려면 launchd.
|
|
166
|
+
**같은 프로젝트**를 역할별 봇으로 나눌 수도 있습니다. 예를 들어 개발자 봇과 기획자 봇으로요. 코드는 그대로 두고 config만 역할별로 둡니다.
|
|
197
167
|
|
|
198
|
-
|
|
168
|
+
| 봇 | permissionMode | 역할 |
|
|
169
|
+
|---|---|---|
|
|
170
|
+
| 개발자 | `bypassPermissions` | 구현·수정·테스트·git |
|
|
171
|
+
| 기획자 | `plan` | 기능 제안·스펙·UX 방향 |
|
|
199
172
|
|
|
200
|
-
|
|
173
|
+
- `persona`에 역할 프롬프트를 넣으면 그 봇의 정체성이 됩니다. (텔레그램용 간결 지침은 자동으로 같이 붙습니다.)
|
|
174
|
+
- 같은 폴더를 공유한다면 쉘을 쓰는 봇(`bypassPermissions`)은 하나로 제한하는 편이 안전합니다. 동시 편집 충돌을 피할 수 있습니다.
|
|
175
|
+
- `state` 파일 이름은 config 이름에서 만들어집니다 (`dev.config.json` → `dev.config.state.json`). 같은 폴더에 config가 여러 개여도 맥락이 안 섞입니다.
|
|
201
176
|
|
|
202
|
-
|
|
203
|
-
**LaunchAgent**라서 claude의 키체인/OAuth 인증을 그대로 사용함.
|
|
177
|
+
## 상시 실행 (launchd)
|
|
204
178
|
|
|
205
|
-
|
|
179
|
+
맥을 재부팅하거나 봇이 죽어도 자동으로 다시 뜨게 하려면 launchd를 씁니다. 로그인 세션에서 도는 LaunchAgent라서 `claude`의 키체인/OAuth 인증을 그대로 사용합니다.
|
|
206
180
|
|
|
207
|
-
`com.
|
|
181
|
+
저장소의 `com.claudebot.example.plist`를 복사해 쓰면 됩니다. 먼저 경로부터 확인하세요.
|
|
208
182
|
|
|
209
183
|
```sh
|
|
210
|
-
which node # ProgramArguments 첫 줄의 node 경로와
|
|
211
|
-
which claude #
|
|
184
|
+
which node # ProgramArguments 첫 줄의 node 경로와 같은지
|
|
185
|
+
which claude # 이 경로가 PATH(EnvironmentVariables)에 포함됐는지
|
|
212
186
|
```
|
|
213
187
|
|
|
214
|
-
plist에서
|
|
215
|
-
|
|
216
|
-
- `ProgramArguments`
|
|
217
|
-
- `WorkingDirectory` —
|
|
218
|
-
- `EnvironmentVariables > PATH` —
|
|
188
|
+
plist에서 맞춰야 할 항목:
|
|
189
|
+
|
|
190
|
+
- `ProgramArguments` — node 절대경로, `bot.mjs` 절대경로, config 절대경로
|
|
191
|
+
- `WorkingDirectory` — 작업 폴더
|
|
192
|
+
- `EnvironmentVariables > PATH` — node·claude 경로 포함
|
|
219
193
|
- `StandardOutPath` / `StandardErrorPath` — 로그 파일 경로
|
|
194
|
+
- `Label` — 봇마다 고유하게 (예: `com.claudebot.myproj`)
|
|
220
195
|
|
|
221
|
-
|
|
196
|
+
등록과 관리:
|
|
222
197
|
|
|
223
198
|
```sh
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.cube.claudebot.plist
|
|
227
|
-
```
|
|
228
|
-
|
|
229
|
-
> 최신 macOS 권장 방식은 `bootstrap`/`bootout`. 구버전(`load`/`unload`)도 동작하지만
|
|
230
|
-
> deprecated 경고가 뜰 수 있음. `bootstrap`이 안 되면 `launchctl load ~/Library/LaunchAgents/com.cube.claudebot.plist`로 대체.
|
|
199
|
+
cp com.claudebot.example.plist ~/Library/LaunchAgents/
|
|
200
|
+
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.claudebot.example.plist
|
|
231
201
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
```sh
|
|
235
|
-
launchctl list | grep claudebot # 등록·동작 확인 (PID가 보이면 실행 중)
|
|
236
|
-
tail -f bot.log # 실행 로그
|
|
237
|
-
tail -f bot.error.log # 에러 로그
|
|
202
|
+
launchctl list | grep claudebot # 상태 확인 (PID가 보이면 실행 중)
|
|
203
|
+
tail -f bot.log # 로그
|
|
238
204
|
|
|
239
205
|
# 중지
|
|
240
|
-
launchctl bootout gui/$(id -u) ~/Library/LaunchAgents/com.
|
|
206
|
+
launchctl bootout gui/$(id -u) ~/Library/LaunchAgents/com.claudebot.example.plist
|
|
241
207
|
|
|
242
|
-
# 코드 수정 후 재시작
|
|
243
|
-
launchctl bootout gui/$(id -u) ~/Library/LaunchAgents/com.
|
|
244
|
-
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.
|
|
208
|
+
# 코드 수정 후 재시작
|
|
209
|
+
launchctl bootout gui/$(id -u) ~/Library/LaunchAgents/com.claudebot.example.plist
|
|
210
|
+
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.claudebot.example.plist
|
|
245
211
|
```
|
|
246
212
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
- **`launchctl list`에 PID 없이 에러 코드만 보임** → `bot.error.log` 확인. 보통 node/claude
|
|
250
|
-
경로 문제(`command not found`)거나 `config.json` 누락.
|
|
251
|
-
- **봇이 응답 없음** → claude 인증 만료일 수 있음. 터미널에서 `node bot.mjs` 직접 실행해
|
|
252
|
-
`claude` 로그인 상태부터 확인.
|
|
253
|
-
- **맥이 잠자기 모드면 폴링도 멈춤** → 시스템 설정 > 배터리/전원에서 절전 해제 권장.
|
|
254
|
-
- **"폴링 오류" 반복 (ETIMEDOUT)** → 일부 네트워크에서 IPv6 경로가 막혀 Node의 fetch가
|
|
255
|
-
api.telegram.org(IPv6 보유)에서 타임아웃나는 문제. `bot.mjs`가 IPv4 우선
|
|
256
|
-
(`dns.setDefaultResultOrder('ipv4first')` + 자동선택 끄기)으로 이미 회피하도록 돼 있음.
|
|
257
|
-
그래도 안 되면 `curl https://api.telegram.org` 로 네트워크/방화벽부터 확인.
|
|
213
|
+
> 최신 macOS는 `bootstrap`/`bootout`을 권장합니다. 구버전 `load`/`unload`도 동작하지만 deprecated 경고가 뜰 수 있습니다.
|
|
258
214
|
|
|
259
|
-
|
|
215
|
+
## 자주 겪는 문제
|
|
260
216
|
|
|
261
|
-
|
|
217
|
+
- **`launchctl list`에 PID 없이 에러 코드만 보임** — `bot.error.log`를 확인하세요. 보통 node/claude 경로 문제이거나 config 누락입니다.
|
|
218
|
+
- **봇이 응답하지 않음** — `claude` 인증이 만료됐을 수 있습니다. 터미널에서 `node bot.mjs`를 직접 실행해 로그인 상태부터 확인하세요.
|
|
219
|
+
- **맥이 잠자기에 들어가면 폴링도 멈춤** — 시스템 설정 > 배터리/전원에서 절전을 풀어두세요.
|
|
220
|
+
- **폴링 오류 반복 (ETIMEDOUT)** — 일부 네트워크는 IPv6 경로가 막혀 있어 `fetch`가 타임아웃 납니다. `bot.mjs`는 IPv4를 우선하도록 이미 처리해 뒀습니다. 그래도 안 되면 `curl https://api.telegram.org`로 네트워크부터 확인하세요.
|
|
262
221
|
|
|
263
|
-
|
|
264
|
-
그 힘이 곧 위험이다. 노출 전에 반드시 읽을 것.
|
|
222
|
+
## 보안
|
|
265
223
|
|
|
266
|
-
|
|
224
|
+
이 봇은 **채팅으로 받은 메시지를 머신에서 명령으로 실행합니다.** 편한 만큼 위험하니 아래는 꼭 지키세요.
|
|
267
225
|
|
|
268
|
-
|
|
269
|
-
폰 잠금과 텔레그램 계정 2단계 인증(2FA)을 켜둘 것.
|
|
270
|
-
2. **봇 토큰을 가진 사람.** 토큰은 봇의 비밀번호다. 토큰만 있으면 들어오는 메시지를 읽고 봇을 사칭할 수
|
|
271
|
-
있다. `allowedChatId` 화이트리스트가 명령 *실행*은 여전히 막아주지만(텔레그램이 부여하는 `chatId`는
|
|
272
|
-
위조 불가), **토큰 유출은 사고로 취급**하라. `@BotFather` → `/revoke`로 폐기하고 새로 발급할 것.
|
|
273
|
-
3. **프롬프트 인젝션.** 웹페이지·파일·이슈 내용을 봇에 넘기며 처리시키면, 그 안에 숨은 악성 지시가
|
|
274
|
-
Claude를 조종할 수 있다. 신뢰할 수 없는 콘텐츠를 `bypassPermissions` 봇에 그대로 흘려넣지 말 것.
|
|
226
|
+
**누가 명령을 실행할 수 있나**
|
|
275
227
|
|
|
276
|
-
|
|
228
|
+
- **허가된 채팅** — `allowedChatId`로 허용한 텔레그램 계정에 접근할 수 있는 사람. 폰 잠금과 텔레그램 2FA를 켜두세요.
|
|
229
|
+
- **봇 토큰을 가진 사람** — 토큰은 봇의 비밀번호입니다. 토큰만으로 메시지를 읽고 봇을 사칭할 수 있습니다. `allowedChatId`가 명령 실행은 막아주지만(텔레그램이 주는 chatId는 위조 불가), 토큰이 새면 사고로 보고 `@BotFather`의 `/revoke`로 폐기하세요.
|
|
230
|
+
- **프롬프트 인젝션** — 외부 웹페이지나 파일을 봇에 넘겨 처리시키면, 그 안에 숨은 지시가 Claude를 조종할 수 있습니다. 신뢰할 수 없는 내용을 `bypassPermissions` 봇에 그대로 넣지 마세요.
|
|
277
231
|
|
|
278
|
-
|
|
279
|
-
설정 후에는 그 채팅만 명령 가능 — 이게 유일한 인증 계층이므로 반드시 채워야 한다.
|
|
280
|
-
- **토큰을 자격증명처럼 보호.** `config.json`·`state.json`은 `.gitignore`에 있어 커밋되지 않는다 —
|
|
281
|
-
그대로 둘 것. 토큰을 이슈·로그·스크린샷에 절대 붙여넣지 말 것. 시작 로그는 토큰을 가린다
|
|
282
|
-
(`token: <redacted>`) — 되살리지 말 것.
|
|
283
|
-
- **샌드박스는 없다.** 봇은 `claude`를 *네* 계정 권한으로 실행한다. 네 파일시스템, SSH/git 자격증명,
|
|
284
|
-
Claude OAuth/키체인 세션에 그대로 접근한다. 네가 할 수 있는 건 봇도 할 수 있다.
|
|
232
|
+
**꼭 지킬 것**
|
|
285
233
|
|
|
286
|
-
|
|
234
|
+
- `allowedChatId`를 반드시 설정하세요. 설정 전에는 봇이 아무것도 실행하지 않고 chatId만 알려줍니다. 이게 유일한 인증 수단입니다.
|
|
235
|
+
- 토큰을 자격증명처럼 다루세요. 이슈·로그·스크린샷에 붙여넣지 마세요. 시작 로그는 토큰을 `<redacted>`로 가립니다.
|
|
236
|
+
- 샌드박스는 없습니다. 봇은 `claude`를 내 계정 권한으로 실행합니다. 내 파일, SSH/git 자격증명, Claude 인증 세션에 그대로 접근합니다.
|
|
287
237
|
|
|
288
|
-
|
|
238
|
+
**권한 모드 선택**
|
|
289
239
|
|
|
290
240
|
| 모드 | 허용 범위 | 권장 상황 |
|
|
291
241
|
|---|---|---|
|
|
292
|
-
| `plan` |
|
|
293
|
-
| `acceptEdits` | 파일 편집
|
|
294
|
-
| `bypassPermissions` |
|
|
242
|
+
| `plan` | 읽기·계획만 | Q&A, 코드 리뷰, 기획자 페르소나 |
|
|
243
|
+
| `acceptEdits` | 파일 편집 자동, 쉘 등은 제한 | 기본값으로 무난 |
|
|
244
|
+
| `bypassPermissions` | 쉘 포함 전부 자동 | 채팅 한 줄이 임의 코드 실행임을 감수할 때 |
|
|
295
245
|
|
|
296
|
-
|
|
246
|
+
- 자율 쉘·git이 꼭 필요한 게 아니면 `acceptEdits`를 쓰세요.
|
|
247
|
+
- `projectDir`는 홈 디렉터리가 아니라 특정 프로젝트를 가리키게 해 피해 범위를 줄이세요.
|
|
248
|
+
- 페르소나 봇을 여럿 둘 땐 하나만 `bypassPermissions`로 두고 나머지는 `plan`으로.
|
|
249
|
+
- 상시 가동한다면 전용 계정이나 VM도 고려해 보세요.
|
|
297
250
|
|
|
298
|
-
|
|
299
|
-
- `projectDir`는 홈 디렉터리가 아니라 **특정 프로젝트**를 가리키게 해 피해 범위를 줄일 것.
|
|
300
|
-
- 멀티 페르소나에서는 **하나의** 봇만 `bypassPermissions`로 두고 나머지는 `plan`으로.
|
|
301
|
-
- 상시 가동할 거면 전용 사용자 계정이나 VM에서 돌리는 것도 고려.
|
|
251
|
+
보안 이슈는 공개로 올리기보다 GitHub 이슈(민감한 내용은 메인테이너에게 비공개)로 알려주세요.
|
|
302
252
|
|
|
303
|
-
|
|
253
|
+
## 라이선스
|
|
304
254
|
|
|
305
|
-
|
|
306
|
-
연락)로 알려주세요.
|
|
255
|
+
MIT © Jongtaek Choi
|
package/README.md
CHANGED
|
@@ -103,43 +103,69 @@ sensitive reports) rather than posting exploit details publicly.
|
|
|
103
103
|
|
|
104
104
|
---
|
|
105
105
|
|
|
106
|
-
##
|
|
106
|
+
## Install & run
|
|
107
107
|
|
|
108
|
-
|
|
109
|
-
`
|
|
108
|
+
This is a standalone CLI/daemon, **not a library** — you don't `import` it. Install it globally (or
|
|
109
|
+
run via `npx`), point a config file at any project, and run it. `projectDir` in the config decides
|
|
110
|
+
which folder Claude works in, independent of where the bot is installed.
|
|
111
|
+
|
|
112
|
+
Prerequisites: **Node 18+** and the **`claude` CLI installed and authenticated** on the host.
|
|
110
113
|
|
|
111
|
-
**
|
|
114
|
+
**Option A — npx (no install)**
|
|
112
115
|
|
|
113
116
|
```sh
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
#
|
|
117
|
+
npx claude-telegram-bot init # writes ./config.json
|
|
118
|
+
# edit config.json (token, projectDir, …)
|
|
119
|
+
npx claude-telegram-bot # runs ./config.json
|
|
117
120
|
```
|
|
118
121
|
|
|
119
|
-
|
|
122
|
+
**Option B — global install (recommended for an always-on daemon)**
|
|
120
123
|
|
|
121
124
|
```sh
|
|
122
|
-
|
|
125
|
+
npm i -g claude-telegram-bot
|
|
126
|
+
|
|
127
|
+
claude-telegram-bot init ~/botconfigs/myproj # writes ~/botconfigs/myproj/config.json
|
|
128
|
+
# edit that config.json (token, projectDir, …)
|
|
129
|
+
claude-telegram-bot ~/botconfigs/myproj/config.json
|
|
123
130
|
```
|
|
124
131
|
|
|
125
|
-
|
|
132
|
+
Run several projects/personas by making one config file each and passing its path —
|
|
133
|
+
`state.json` and `attachments/` live next to that config, so they don't mix.
|
|
126
134
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
# now only you can use it
|
|
133
|
-
```
|
|
135
|
+
> **Keep your config out of git.** The config file holds your bot token. If you drop one inside a git
|
|
136
|
+
> repo, add it (plus `state*.json` and `attachments/`) to *that* project's `.gitignore`. This repo
|
|
137
|
+
> already ignores `config.json`, `config.*.json`, `*.config.json`, `state*.json`, and `attachments/`,
|
|
138
|
+
> so any name like `claudebot.config.json` is covered here — but your own project won't ignore them
|
|
139
|
+
> until you say so.
|
|
134
140
|
|
|
135
|
-
|
|
141
|
+
### First-run steps
|
|
142
|
+
|
|
143
|
+
**1) Create a bot token** — In Telegram, open `@BotFather` → `/newbot` → pick a name and a
|
|
144
|
+
`username` ending in `_bot` → copy the token (looks like `123456789:AA...`). Put it in `config.json`,
|
|
145
|
+
leave `allowedChatId` empty for now.
|
|
146
|
+
|
|
147
|
+
**2) Find your chatId and lock the bot to it** — Start the bot (`claude-telegram-bot …`), send it any
|
|
148
|
+
message in Telegram; it replies with this chat's `chatId`. Put that number into `config.json`
|
|
149
|
+
`allowedChatId` and restart. Now only you can use it. (See [Security](#security) — this is your only
|
|
150
|
+
auth layer.)
|
|
151
|
+
|
|
152
|
+
**3) Use it** — just send messages:
|
|
136
153
|
|
|
137
154
|
- `run the solver tests and commit + push if they pass`
|
|
138
155
|
- `add an edge case to solve-2nd-floor-edges.ts`
|
|
139
156
|
|
|
140
|
-
Commands: `/new` (reset context / new session) · `/id` (show chat ID) · `/help`.
|
|
157
|
+
Commands: `/new` (reset context / new session) · `/cron` (list / add / remove scheduled tasks) · `/restart` (syntax-check & restart the bot) · `/id` (show chat ID) · `/help`.
|
|
158
|
+
|
|
159
|
+
> **`/restart`** runs `node --check` on `bot.mjs` first and **aborts the restart if it has a syntax
|
|
160
|
+
> error** (so a bad edit can't crash-loop the bot), then exits — relying on a process supervisor
|
|
161
|
+
> to relaunch it. Works out of the box with the [launchd setup](#always-on-with-launchd-macos)
|
|
162
|
+
> (`KeepAlive`); under a bare `node bot.mjs` with no supervisor it just stops. Your session resumes
|
|
163
|
+
> after the restart (the id lives in `state.json`).
|
|
164
|
+
|
|
165
|
+
**4) Keep it always on (optional)** — see [Always-on with launchd](#always-on-with-launchd-macos).
|
|
141
166
|
|
|
142
|
-
**
|
|
167
|
+
> **From source** (for hacking on the bot): clone the repo, `cp config.example.json config.json`,
|
|
168
|
+
> then `node bot.mjs [config.json]`. Same behavior as the CLI.
|
|
143
169
|
|
|
144
170
|
---
|
|
145
171
|
|
|
@@ -159,10 +185,12 @@ Edit `config.json`:
|
|
|
159
185
|
| `claudeBin` | Output of `which claude` (absolute path recommended) |
|
|
160
186
|
| `permissionMode` | `plan` / `acceptEdits` / `bypassPermissions` — see [Security](#security) |
|
|
161
187
|
| `model` | Empty = default. Or `opus` / `sonnet`, etc. |
|
|
188
|
+
| `lang` | (optional) UI language. Empty = auto-detect per user (English default, Korean for Korean Telegram clients). Force with `"en"` / `"ko"`. |
|
|
162
189
|
| `name` | (optional) Bot name shown in `/help` — handy for telling multiple bots apart |
|
|
163
190
|
| `persona` | (optional) Role system prompt — defines a persona (developer/planner/…). See below |
|
|
164
191
|
| `appendSystemPrompt` | (optional) Override the default "be concise for Telegram" instruction |
|
|
165
192
|
| `env` | (optional) Extra environment variables passed to the `claude` process |
|
|
193
|
+
| `schedule` | (optional) Cron jobs that run a prompt on a timer — see [Scheduled tasks](#scheduled-tasks-cron) |
|
|
166
194
|
|
|
167
195
|
State (`state.json`) and downloaded `attachments/` are written **next to the config file**, so
|
|
168
196
|
projects stay isolated.
|
|
@@ -171,6 +199,10 @@ projects stay isolated.
|
|
|
171
199
|
|
|
172
200
|
- **Concise mode**: a `--append-system-prompt` is applied by default so replies stay short for
|
|
173
201
|
Telegram. Override it via `appendSystemPrompt` (empty string disables it).
|
|
202
|
+
- **Language**: the bot's own messages (`/help`, command menu, status text) are English by default
|
|
203
|
+
and switch to Korean for users whose Telegram client is Korean. Force one language with `lang`
|
|
204
|
+
(`"en"`/`"ko"`). Claude's actual replies follow the language you write in, regardless. The `/`
|
|
205
|
+
command menu is registered per-language via `setMyCommands`.
|
|
174
206
|
- **Formatting**: the reply's Markdown (bold/code/headings/tables) is converted to Telegram-safe
|
|
175
207
|
HTML. If conversion ever produces invalid HTML, the message is automatically resent as plain text.
|
|
176
208
|
- **Attachments**: send a photo/document/voice/video and it's downloaded into `attachments/`; the
|
|
@@ -178,6 +210,44 @@ projects stay isolated.
|
|
|
178
210
|
- **Sessions**: conversations resume automatically (`--resume`); the last session id is saved in
|
|
179
211
|
`state.json`, so context survives restarts. Use `/new` to start fresh.
|
|
180
212
|
|
|
213
|
+
### Scheduled tasks (cron)
|
|
214
|
+
|
|
215
|
+
Add a `schedule` array to the config to run prompts on a timer — daily briefings, periodic
|
|
216
|
+
checks, reminders. Each entry runs the prompt and sends the result to `allowedChatId`.
|
|
217
|
+
|
|
218
|
+
```json
|
|
219
|
+
"schedule": [
|
|
220
|
+
{ "cron": "0 9 * * 1-5", "label": "Morning brief", "prompt": "Summarize today's open issues and TODOs" },
|
|
221
|
+
{ "cron": "*/30 * * * *", "prompt": "Check CI status; only reply if something is red" }
|
|
222
|
+
]
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
- **`cron`** — standard 5-field expression `minute hour day-of-month month day-of-week`
|
|
226
|
+
(e.g. `0 9 * * 1-5` = 09:00 on weekdays). Supports `*`, lists (`1,3,5`), ranges (`1-5`),
|
|
227
|
+
and steps (`*/15`). Day-of-week `0` and `7` both mean Sunday. Times use the **host's local
|
|
228
|
+
timezone**. No external dependency — the parser lives in `bot.mjs`.
|
|
229
|
+
- **`prompt`** (required) — the message sent to Claude. **`label`** (optional) — a short name
|
|
230
|
+
shown in the reply footer and in `/cron`.
|
|
231
|
+
- **Fresh session**: scheduled jobs run in their **own session** so they never pollute your
|
|
232
|
+
interactive conversation context (`state.json` stays yours). They share the single-task lock,
|
|
233
|
+
so a job is **skipped** (logged) if a task is already running when it fires.
|
|
234
|
+
|
|
235
|
+
**Add jobs from the chat — in plain language:**
|
|
236
|
+
|
|
237
|
+
```
|
|
238
|
+
/cron add summarize open issues every weekday at 9am
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
The bot asks Claude to turn that into a cron expression, **echoes back what it understood**
|
|
242
|
+
(so you can catch a misread), and saves it to `state.json` — **no restart needed**. Dynamic
|
|
243
|
+
jobs get an id; manage them with:
|
|
244
|
+
|
|
245
|
+
- `/cron` — list everything (config jobs are tagged `[config]`; dynamic ones show `#id`)
|
|
246
|
+
- `/cron add <plain-language request>` — e.g. `/cron add every 30 min, ping me if CI is red`
|
|
247
|
+
- `/cron rm <id>` — remove a dynamic job (config jobs are edited in the file)
|
|
248
|
+
|
|
249
|
+
Config-defined jobs still require a restart to change; only chat-added jobs are live.
|
|
250
|
+
|
|
181
251
|
---
|
|
182
252
|
|
|
183
253
|
## Running multiple projects
|
package/bot.mjs
CHANGED
|
Binary file
|
package/config.example.json
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
{
|
|
2
|
-
"name": "
|
|
3
|
-
"token": "
|
|
2
|
+
"name": "Bot name (shown in /help, for telling bots apart; optional)",
|
|
3
|
+
"token": "BOT_TOKEN_FROM_BOTFATHER",
|
|
4
4
|
"allowedChatId": "",
|
|
5
5
|
"projectDir": "/ABSOLUTE/PATH/TO/PROJECT",
|
|
6
|
-
"claudeBin": "/
|
|
6
|
+
"claudeBin": "/ABSOLUTE/PATH/TO/claude",
|
|
7
7
|
"permissionMode": "bypassPermissions",
|
|
8
8
|
"model": "",
|
|
9
|
-
"
|
|
9
|
+
"lang": "",
|
|
10
|
+
"persona": "System prompt defining this bot's role/voice (optional). Used to differentiate persona bots (developer/planner/...).",
|
|
10
11
|
"appendSystemPrompt": "",
|
|
11
|
-
"env": {}
|
|
12
|
+
"env": {},
|
|
13
|
+
"schedule": [
|
|
14
|
+
{ "cron": "0 9 * * 1-5", "label": "Morning brief", "prompt": "Summarize today's open issues and TODOs (optional; standard 5-field cron: min hour day month weekday)" }
|
|
15
|
+
]
|
|
12
16
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-telegram-bot",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Drive Claude Code from Telegram — messages run headless `claude -p` in a project dir and replies come back to the chat. Zero dependencies.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|