grok-telegram-bot 2.0.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.
Files changed (106) hide show
  1. package/.env.example +135 -0
  2. package/CHANGELOG.md +598 -0
  3. package/LICENSE +21 -0
  4. package/README.md +644 -0
  5. package/bin/grok-tg.mjs +21 -0
  6. package/docs/INSTALL.md +153 -0
  7. package/docs/UPGRADE.md +253 -0
  8. package/docs/ops/RELEASE_CHECKLIST.md +39 -0
  9. package/package.json +74 -0
  10. package/scripts/setup.mjs +116 -0
  11. package/src/agents/catalog.ts +58 -0
  12. package/src/app/accounts.ts +162 -0
  13. package/src/app/auth-service.ts +136 -0
  14. package/src/app/grok-credentials.ts +103 -0
  15. package/src/app/instance-lock.ts +139 -0
  16. package/src/app/json-store.ts +54 -0
  17. package/src/app/reasoning.ts +30 -0
  18. package/src/app/settings-store.ts +38 -0
  19. package/src/app/stt.ts +53 -0
  20. package/src/app/types.ts +56 -0
  21. package/src/app/updater.ts +234 -0
  22. package/src/app/usage.ts +38 -0
  23. package/src/app/version.ts +41 -0
  24. package/src/bot/account-rotator.ts +52 -0
  25. package/src/bot/auth.ts +38 -0
  26. package/src/bot/bot.ts +225 -0
  27. package/src/bot/chat-controller.ts +317 -0
  28. package/src/bot/commands.ts +52 -0
  29. package/src/bot/deps.ts +67 -0
  30. package/src/bot/file-ingest.ts +190 -0
  31. package/src/bot/handlers/accounts.ts +220 -0
  32. package/src/bot/handlers/auth.ts +64 -0
  33. package/src/bot/handlers/control.ts +103 -0
  34. package/src/bot/handlers/document.ts +112 -0
  35. package/src/bot/handlers/history.ts +63 -0
  36. package/src/bot/handlers/kill.ts +54 -0
  37. package/src/bot/handlers/mcp.ts +206 -0
  38. package/src/bot/handlers/menu.ts +220 -0
  39. package/src/bot/handlers/message.ts +103 -0
  40. package/src/bot/handlers/photo.ts +123 -0
  41. package/src/bot/handlers/projects.ts +183 -0
  42. package/src/bot/handlers/running.ts +181 -0
  43. package/src/bot/handlers/session-card.ts +81 -0
  44. package/src/bot/handlers/session-kill.ts +95 -0
  45. package/src/bot/handlers/sessions.ts +148 -0
  46. package/src/bot/handlers/system.ts +51 -0
  47. package/src/bot/handlers/tasks.ts +224 -0
  48. package/src/bot/handlers/usage.ts +38 -0
  49. package/src/bot/handlers/voice.ts +55 -0
  50. package/src/bot/image-return.ts +69 -0
  51. package/src/bot/menu/ephemeral.ts +117 -0
  52. package/src/bot/menu/keyboard.ts +49 -0
  53. package/src/bot/menu/refresh.ts +13 -0
  54. package/src/bot/menu/status-panel.ts +173 -0
  55. package/src/bot/permission-service.ts +149 -0
  56. package/src/bot/prompt-content.ts +64 -0
  57. package/src/bot/prompt-retry.ts +70 -0
  58. package/src/bot/reauth-controller.ts +297 -0
  59. package/src/bot/registry.ts +186 -0
  60. package/src/bot/reply-context.ts +77 -0
  61. package/src/bot/session-fork.ts +35 -0
  62. package/src/bot/session-runtime.ts +1048 -0
  63. package/src/bot/telegram-io.ts +109 -0
  64. package/src/bot/typing.ts +35 -0
  65. package/src/bot/wizard/task-wizard.ts +214 -0
  66. package/src/cli.ts +126 -0
  67. package/src/config.ts +248 -0
  68. package/src/grok/client.ts +617 -0
  69. package/src/grok/models.ts +50 -0
  70. package/src/grok/session-log.ts +148 -0
  71. package/src/grok/transport.ts +51 -0
  72. package/src/grok/types.ts +136 -0
  73. package/src/index.ts +84 -0
  74. package/src/logger.ts +78 -0
  75. package/src/mcp/config.ts +120 -0
  76. package/src/mcp/probe.ts +218 -0
  77. package/src/mcp/types.ts +68 -0
  78. package/src/projects/manager.ts +99 -0
  79. package/src/render/chunk.ts +57 -0
  80. package/src/render/diff.ts +48 -0
  81. package/src/render/escape.ts +22 -0
  82. package/src/render/file-summary.ts +111 -0
  83. package/src/render/hashtags.ts +34 -0
  84. package/src/render/markdown.ts +130 -0
  85. package/src/render/progress-estimate.ts +63 -0
  86. package/src/render/progress.ts +80 -0
  87. package/src/render/subagent.ts +75 -0
  88. package/src/render/tool-call.ts +196 -0
  89. package/src/service/index.ts +24 -0
  90. package/src/service/linux.ts +85 -0
  91. package/src/service/macos.ts +101 -0
  92. package/src/service/platform.ts +64 -0
  93. package/src/service/types.ts +36 -0
  94. package/src/service/windows.ts +198 -0
  95. package/src/sessions/history.ts +225 -0
  96. package/src/sessions/process.ts +30 -0
  97. package/src/sessions/store.ts +133 -0
  98. package/src/sessions/tail.ts +86 -0
  99. package/src/sessions/types.ts +26 -0
  100. package/src/stream/streamer.ts +261 -0
  101. package/src/tasks/runner.ts +82 -0
  102. package/src/tasks/schedule.ts +142 -0
  103. package/src/tasks/scheduler.ts +53 -0
  104. package/src/tasks/store.ts +80 -0
  105. package/src/tasks/types.ts +33 -0
  106. package/tsconfig.json +19 -0
package/README.md ADDED
@@ -0,0 +1,644 @@
1
+ # Grok Telegram Bot 🤖
2
+
3
+ > **Control [Grok CLI](https://grok.dev/cli/) from Telegram.** Your AI coding
4
+ > assistant in your pocket — switch projects, resume and attach to live coding
5
+ > sessions, stream answers with diffs, queue follow-ups, and run it 24/7 as a
6
+ > background service on Windows, Linux, and macOS.
7
+
8
+ ![Node](https://img.shields.io/badge/node-%3E%3D20-339933?logo=node.js&logoColor=white)
9
+ ![Platforms](https://img.shields.io/badge/platforms-Windows%20%7C%20Linux%20%7C%20macOS-blue)
10
+ ![License](https://img.shields.io/badge/license-MIT-green)
11
+ ![Powered by](https://img.shields.io/badge/powered%20by-Grok%20CLI-orange)
12
+
13
+ A professional Telegram bridge that drives the official **Grok Build CLI**
14
+ (`grok`) over the **Agent Client Protocol (ACP)** — `grok agent stdio` — and
15
+ turns it into a mobile, always-on AI pair programmer. Sign in with your xAI
16
+ account (SuperGrok / X Premium+), send a message from anywhere, and watch Grok
17
+ plan, read files, run commands, and edit code on your machine — with live typing
18
+ indicators, clean Telegram markdown, and unified edit diffs.
19
+
20
+ Inspired by [`ajitnk-lab/kiro-acp-telegram-bot`](https://github.com/ajitnk-lab/kiro-acp-telegram-bot)
21
+ and extended into a full multi-session client.
22
+
23
+ ---
24
+
25
+ ## ✨ Features
26
+
27
+ | Capability | What it does |
28
+ |---|---|
29
+ | 🗂 **Projects** | `/projects` browses your folders and runs Grok in the one you pick. |
30
+ | ♻️ **Resume sessions** | `/sessions` lists recent Grok sessions; tap to resume one (`grok --session <id>`). |
31
+ | 🟢 **Connect to live sessions** | `/active` shows sessions running **right now** on your PC. Watch them live, or continue them — see below. |
32
+ | 🛑 **Kill a session / PID** | Each live `/sessions` · `/active` card has a **🛑 Kill · pid N** button (confirm-guarded) that stops that session's process and its child tree; `/killall` stops them all. The bot's own agent is never killable. |
33
+ | 📡 **Live watch** | Follow a running session read-only in real time (tails its event log). |
34
+ | 🧭 **Always-visible menu** | A persistent keyboard plus a pinned status panel that appears while a task runs (and clears when idle), showing your current **project, agent, reasoning effort, model, session and queue**. |
35
+ | ⏰ **Scheduled tasks** | Create prompts that run on a schedule (once / daily / weekly / monthly / every-N-minutes) in a chosen project, delivered back to your chat. |
36
+ | 🖼 **Multi-image prompts** | Send one or many photos (albums included) with a caption — all attached to the prompt for the agent to analyze. |
37
+ | 📜 **History** | `/history` shows the latest messages of any session. |
38
+ | 🧩 **MCP control** | `/mcp` lists MCP servers, **health-checks** them (which connected / failed and why), and **enables/disables** them — then restarts the agent to apply. |
39
+ | 👥 **Subagent visibility** | When Grok delegates to subagents and waits on them, you see each one **start / work / finish** plus a live `🤖 N running` summary — and subagent permission prompts route to your chat. |
40
+ | 📈 **Task progress bar** | The agent appends a `{progress: N%}` marker; the bot hides it and shows a **green 0–100% loading bar** on the live message, in the status panel, and on session cards (`SHOW_PROGRESS`). |
41
+ | 🔐 **Sign in from chat** | `/reauth` signs you in without a terminal — **🔑 Sign in** runs `grok login` (any verification link/code streams to your chat), or **📥 Import** an existing on-host login; the agent restarts under the new identity. |
42
+ | 👥 **Multiple accounts** | `/accounts` saves several Grok **sign-ins** (custom names) and switches between them in a tap — copies that login back over `~/.grok/auth.json` and restarts so sessions re-bind under the new account. |
43
+ | 🔁 **Auto-rotate on give-up** | When a turn exhausts its retries, optionally cycle through your other saved accounts once and retry on each — the first that works wins (toggle in `/accounts`). |
44
+ | 🪙 **Credits & usage** | The `✅ Done` line and `/usage` show credits used (when Grok reports them), turns this session, and account info. |
45
+ | ⌨️ **Typing indicator** | Stays on for the whole turn, even through long tool chains. |
46
+ | 📥 **Queued follow-ups** | Message while Grok is busy — it's queued and runs next. `/btw` runs it ASAP (now if idle, else right after the current task); `/flush` runs the queue now. |
47
+ | ✏️ **Edit diffs** | File edits show as unified `diff` blocks with `+N -M` stats. |
48
+ | 💬 **Quality markdown** | Converts agent markdown to Telegram **MarkdownV2** with safe escaping and code-fence-aware splitting. |
49
+ | 🔁 **Self-healing** | Auto-restarts the Grok agent with backoff and re-binds your session. |
50
+ | 🖥 **Runs 24/7** | 1-click install as a background service that starts on boot — Windows, Linux, macOS, auto-detected. |
51
+ | 🔒 **Access control** | Restrict to specific Telegram user IDs. |
52
+
53
+ ---
54
+
55
+ ## 📊 How it compares
56
+
57
+ | Capability | **This bot** | Other Grok Telegram bots |
58
+ |---|:---:|:---:|
59
+ | Connect Grok CLI to Telegram (ACP) | ✅ | ✅ |
60
+ | Switch between projects | ✅ | ❌ |
61
+ | Resume saved sessions | ✅ | ❌ |
62
+ | Attach to **live** PC sessions (watch / fork) | ✅ | ❌ |
63
+ | **Kill a session by PID** (or all at once) | ✅ | ❌ |
64
+ | **Live task-progress bars** (`{progress: N%}`) | ✅ | ❌ |
65
+ | **Sign in from chat** (`/reauth`) | ✅ | ❌ |
66
+ | **Multiple saved accounts** + one-tap switch (`/accounts`) | ✅ | ❌ |
67
+ | **Auto-rotate accounts** when a turn gives up | ✅ | ❌ |
68
+ | Multiple isolated sessions | ✅ | ❌ (single shared) |
69
+ | Queued follow-ups while busy | ✅ | ❌ |
70
+ | **Scheduled tasks** (cron-like) | ✅ | ❌ |
71
+ | **Multi-image** prompts (albums) | ✅ | ❌ |
72
+ | Unified **edit diffs** | ✅ | ❌ |
73
+ | Persistent menu + live status panel | ✅ | ❌ |
74
+ | Agent / reasoning / model menus | ✅ | ❌ |
75
+ | Combined, throttled output (no spam) | ✅ | ❌ |
76
+ | Auto-restart + session re-bind | ✅ | ❌ |
77
+ | 24/7 cross-platform service | ✅ | ❌ |
78
+ | 1-click install | ✅ | ❌ |
79
+
80
+ ---
81
+
82
+ ## ⚡ Install from npm
83
+
84
+ The fastest way — one command installs the global **`grok-tg`** CLI (ships with
85
+ the `tsx` runtime, no build step):
86
+
87
+ ```bash
88
+ npm install -g grok-telegram-bot
89
+ ```
90
+
91
+ By default your config lives in a **canonical, path-independent home** —
92
+ `~/.grok/tg/` (its `.env`, `logs/`, `data/`) — so the bot loads the **same**
93
+ `.env` no matter which folder you start it from. Run `grok-tg setup --path` to
94
+ print the exact location. (A `.env` in the current folder is still honoured
95
+ first, so existing per-folder checkouts keep working.)
96
+
97
+ ```bash
98
+ grok-tg setup # auto-detects grok, writes ~/.grok/tg/.env
99
+ grok-tg setup --path # print the .env location
100
+ # edit that .env: set TELEGRAM_BOT_TOKEN and ALLOWED_USERS
101
+ grok-tg run # foreground …
102
+ grok-tg install # … or install as a 24/7 background service
103
+ ```
104
+
105
+ The bot is **single-instance per token**: starting it again terminates any
106
+ ghost/duplicate that was still polling Telegram (the usual cause of a stale
107
+ "⛔ Not authorized"), so the fresh process with your current `.env` wins. A
108
+ plain `grok-tg run` yields to an already-running background service instead.
109
+
110
+ Startup options: `grok-tg setup [--path] | run | install | status | logs [n] |
111
+ stop | restart | uninstall`. Or try it without installing: `npx
112
+ grok-telegram-bot setup`. See **[docs/INSTALL.md](./docs/INSTALL.md)** for the
113
+ full guide.
114
+
115
+ **Already installed?** See **[docs/UPGRADE.md](./docs/UPGRADE.md)** to update to
116
+ the newest version — global npm installs auto-update when idle, or run
117
+ `npm install -g grok-telegram-bot@latest` and `grok-tg restart`.
118
+
119
+ ---
120
+
121
+ ## 🚀 1-click install
122
+
123
+ Clone or download, then run the installer for your OS. It installs
124
+ dependencies, auto-detects `grok`, writes `.env`, asks for your bot token,
125
+ and optionally sets up the background service.
126
+
127
+ **Windows** — double-click `install.cmd` (or in a terminal):
128
+
129
+ ```powershell
130
+ .\install.cmd
131
+ ```
132
+
133
+ **Linux / macOS**:
134
+
135
+ ```bash
136
+ chmod +x install.sh && ./install.sh
137
+ ```
138
+
139
+ ### Prerequisites
140
+
141
+ - **Grok Build CLI** (`grok`) installed — `curl -fsSL https://x.ai/cli/install.sh | bash`
142
+ (Windows: `irm https://x.ai/cli/install.ps1 | iex`). Run `grok --version` to confirm.
143
+ - A **SuperGrok** or **X Premium+** subscription, and a one-time sign-in: run
144
+ `grok login` (browser OIDC) on the host, or use the bot's `/reauth`. On a
145
+ headless host with no browser you can instead set `XAI_API_KEY`.
146
+ - **Node.js 20+**.
147
+ - A **bot token** from [@BotFather](https://t.me/BotFather).
148
+ - Your **Telegram user ID** from [@userinfobot](https://t.me/userinfobot).
149
+
150
+ > ⚠️ **Use a dedicated bot token.** Telegram allows only one long-polling
151
+ > consumer per token. If you also run another Telegram bot (e.g. a Kiro bridge)
152
+ > on the **same** token, they will clash on `getUpdates`. This bot keeps its
153
+ > own config home (`~/.grok/tg`) and only ever manages its **own** sessions
154
+ > (`<data>/sessions`), so it never touches Kiro's processes or session locks —
155
+ > but give it its own BotFather token to avoid the polling conflict.
156
+
157
+ ---
158
+
159
+ ## 🧑‍💻 Manual setup
160
+
161
+ ```bash
162
+ npm install
163
+ npm run setup # auto-detects grok + project roots, writes .env
164
+ # edit .env: set TELEGRAM_BOT_TOKEN and ALLOWED_USERS
165
+ npm start
166
+ ```
167
+
168
+ No build step — TypeScript runs directly via `tsx`.
169
+
170
+ ---
171
+
172
+ ## 🛠 Run as a background service (daemon)
173
+
174
+ The bot installs as a **user-level** service that starts automatically on boot.
175
+ The platform is auto-detected:
176
+
177
+ | OS | Mechanism | Starts on |
178
+ |---|---|---|
179
+ | Windows | Hidden Scheduled Task (elevated) · per-user **Startup folder** (no admin) | logon |
180
+ | Linux | systemd **user** service (+ linger) | boot |
181
+ | macOS | launchd LaunchAgent | login |
182
+
183
+ On Windows, registering a logon-triggered Scheduled Task needs admin, so from a
184
+ normal terminal `grok-tg install` falls back to a hidden launcher in your
185
+ per-user **Startup folder** (starts at logon, no elevation). Run it from an
186
+ **elevated** terminal to use the Scheduled Task instead; either way `status`,
187
+ `stop`, `restart` and `uninstall` work the same.
188
+
189
+ ```bash
190
+ npm run install:service # install + start, enable autostart
191
+ npm run service -- status # show install + running state
192
+ npm run service -- stop
193
+ npm run service -- restart
194
+ npm run service -- logs 200 # tail the log file
195
+ npm run uninstall:service # stop + remove
196
+ ```
197
+
198
+ Or use the `grok-tg` command (if linked): `grok-tg install | status | logs`.
199
+
200
+ Logs are written to `logs/grok-telegram-bot.log` (rotated at 5 MB).
201
+
202
+ ---
203
+
204
+ ## 💬 Commands
205
+
206
+ ```
207
+ /menu Show the persistent menu keyboard
208
+ /projects List · /projects <q> search · /projects <path> open any folder · /projects new <name>
209
+ /sessions List & resume sessions (active first) · /sessions <q> to filter
210
+ /active Sessions running now on the PC
211
+ /running Sessions this chat controls — switch between them
212
+ /killall Kill all active sessions on the PC (with confirm)
213
+ /mcp Inspect MCP servers · health-check · enable/disable
214
+ /tasks Manage scheduled tasks
215
+ /newtask Create a scheduled task (wizard)
216
+ /history Show recent conversation history
217
+ /new Start a fresh session here
218
+ /status Current session, project & queue
219
+ /usage Account info & current context usage
220
+ /btw <text> Run it now if idle, else queue to run right after the current task
221
+ /flush Send queued follow-ups now
222
+ /queue Show queued follow-ups
223
+ /clearqueue Clear the queue
224
+ /cancel Stop the current turn
225
+ /unwatch Stop following a live session
226
+ /model <id> Switch the model for this session
227
+ /restart Restart the Grok agent
228
+ /reauth Sign in to Grok — 🔑 Sign in (grok login) or 📥 Import an existing login
229
+ /accounts Save & switch between multiple Grok accounts · auto-rotate on errors
230
+ /help Show help
231
+ ```
232
+
233
+ Anything that isn't a command is sent to Grok as a prompt. While a turn is
234
+ running, your messages are queued and sent automatically when it finishes.
235
+
236
+ ---
237
+
238
+ ## 🧭 The menu & status panel
239
+
240
+ A tiny **persistent bar** sits under the message box — **☰ Menu · 🧭 Running ·
241
+ ⏹ Stop** — so common actions are one tap away without clutter. Tap **☰ Menu**
242
+ (or `/menu`) to open a clean, grouped **inline menu**: Project · New · Running ·
243
+ Sessions · Agent · Model · Reasoning · Tasks · Status · Usage · Stop · Kill all.
244
+ The bar can be hidden (🙈) and restored (⌨️ Show bar or `/menu`).
245
+
246
+ While a task is running, a **pinned status panel** appears at the top of the chat
247
+ showing your current **task progress, activity, queue, project, session, context
248
+ %, agent, reasoning effort and model** (and how many sessions the chat controls),
249
+ updating live — and it's **removed when the session goes idle** so the chat stays
250
+ clean between tasks (use **Status** in the menu to see it on demand any time).
251
+ Pick **Agent**, **Reasoning** or **Model** from the inline menu (reasoning steers
252
+ how thoroughly the agent works: Minimal → Max).
253
+
254
+ ## ⏰ Scheduled tasks
255
+
256
+ A task is a **prompt + a project + a schedule**. When it fires, the bot opens a
257
+ session in that project, runs the prompt, and delivers the result to your chat.
258
+
259
+ - **/newtask** (or the ➕ button) launches a guided wizard: name → prompt →
260
+ project → schedule → confirm.
261
+ - **Schedules**: `once` at a date/time, `daily` at HH:MM, `weekly` (e.g. `Mon 09:00`),
262
+ `monthly` (e.g. `15 09:00`), or `interval` (every N minutes).
263
+ - **/tasks** lists everything with buttons to **run now, enable/disable, edit**
264
+ (rename, prompt, project, reschedule) and **delete**.
265
+
266
+ Tasks are stored in `data/tasks.json` and survive restarts; the scheduler runs
267
+ them whether you're online or not (great with the 24/7 service).
268
+
269
+ ## 🖼 Sending images
270
+
271
+ Send one or several photos — including a Telegram **album** — with an optional
272
+ caption. The bot downloads them and attaches them all to the prompt as image
273
+ content blocks, so the agent can analyze them together. Images sent while Grok
274
+ is busy are queued with your next turn.
275
+
276
+ **Images come back too:** when the agent produces images during a turn (e.g.
277
+ takes screenshots while testing an app), the bot detects the freshly-written
278
+ files and sends them back to Telegram automatically (`SEND_AGENT_IMAGES`).
279
+
280
+ ## 🎙 Sending voice
281
+
282
+ Send a voice note (or audio file) and the bot transcribes it and runs it as a
283
+ prompt. Configure any OpenAI/Whisper-compatible endpoint via `STT_API_URL` in
284
+ `.env`; leave `STT_LANGUAGE` blank for automatic detection (English, Russian,
285
+ Romanian/Moldovan, and ~100 more).
286
+
287
+ ## 📎 Sending files
288
+
289
+ Send any **document** and the bot resolves it. **Text-like files** — a long
290
+ message your Telegram client turned into a `.txt`, plus code, logs, JSON, CSV,
291
+ Markdown, and more — are downloaded, decoded, and inlined into the prompt (up to
292
+ `DOC_MAX_CHARS`, then truncated with a note), so the agent reads the whole thing.
293
+ **Binary files** are saved under `<data>/downloads` and their path is handed to
294
+ the agent to open with its own tools. An optional caption becomes the
295
+ instruction; files sent while Grok is busy are queued with your next turn.
296
+
297
+ ## ↩️ Replying for context
298
+
299
+ **Reply** to any message (yours or the bot's) and the referenced content rides
300
+ along with your new message, so a terse "fix this" or "why?" keeps its meaning.
301
+ If you highlight a specific **quote** while replying, the bot forwards that exact
302
+ excerpt plus the surrounding message. Works for text, photo, voice and file
303
+ prompts alike (long quotes are trimmed to keep prompts lean).
304
+
305
+ ## 📈 Task progress
306
+
307
+ The bot asks the agent to end each message with a `{progress: N%}` marker, then
308
+ **hides the marker** and renders a **green loading bar** from 0–100 %
309
+ (`🟩🟩🟩🟩🟩⬜⬜⬜⬜⬜ 50%`, all-green ✅ at 100 %) so you can see how far along the
310
+ current task is. The bar appears at the bottom of the **live message**, in the
311
+ pinned **status panel**, and on **`/running` and `/sessions` cards**. Markers are
312
+ also stripped from history, replays and previews, so the raw plumbing never
313
+ shows. Turn it off with `SHOW_PROGRESS=false`.
314
+
315
+ That marker is only an instruction the model can ignore — weaker/free models and
316
+ long, tool-heavy turns often emit none, which used to leave the bar empty for the
317
+ whole turn. So when `SHOW_PROGRESS` is on but no marker arrives, the bot falls
318
+ back to a **computed** bar derived from real activity (completed tool calls,
319
+ streamed output, elapsed time): it starts low, climbs as work advances, and fills
320
+ to 100 % when the turn completes. The agent's own marker, when present, always
321
+ takes precedence and the value never decreases. Disable the fallback with
322
+ `PROGRESS_FALLBACK=false`.
323
+
324
+ ## 🔐 Signing in to Grok
325
+
326
+ Grok Build signs in with your **xAI account** (SuperGrok / X Premium+), not an
327
+ API key. Run **`/reauth`** to sign in without touching a terminal:
328
+
329
+ - **🔑 Sign in** — runs `grok login`; if a verification link/code appears it
330
+ streams into the chat so you can approve it on any device. The bot then
331
+ restarts the agent so your next turn runs on the new identity.
332
+ - **📥 Import existing** — adopt a `grok login` already done on this machine
333
+ (`~/.grok/auth.json`).
334
+
335
+ It's refused while a turn is running. You can also sign in up front by running
336
+ `grok login` on the host, or set `XAI_API_KEY` on a headless host.
337
+
338
+ ## 👥 Multiple accounts
339
+
340
+ **`/accounts`** manages several Grok **sign-ins** side by side. Save the current
341
+ login as a named account (auto-named from its email, or **Save as…** with a
342
+ custom name), rename or delete saved ones, and **switch** in a tap — the bot
343
+ copies that account's token back over `~/.grok/auth.json` and restarts the agent
344
+ so your next turn runs under it (the current login is snapshotted first so it's
345
+ never lost). Snapshots live only in git-ignored per-account files.
346
+
347
+ **🔁 Auto-rotate on errors** (toggle here): when a turn exhausts its retries and
348
+ can't recover, the bot cycles through your other saved logins **once**, retrying
349
+ the prompt on each — the first that succeeds stays active; if they all fail it
350
+ stops after one pass. Handy when an account gets throttled or runs out of quota.
351
+
352
+ ---
353
+
354
+ ## 🧭 Working on several sessions at once
355
+
356
+ One chat can drive **multiple Grok sessions** and switch between them. Start a
357
+ session (📁 Project / 🆕 New), and each becomes a "controlled" session. Tap
358
+ **🧭 Running** (or `/running`) to switch: the foreground session streams live
359
+ while the others keep working quietly. When you switch to a session you see its
360
+ recent context and **every message that arrived while you were away** (its
361
+ unread, recovered from the session log). Leave a task running in A, hop to B,
362
+ reply, and come back to A to read what it did. Close a session with ✖ (it isn't
363
+ killed) — or tap **🛑 Kill · pid N** on its `/sessions` · `/active` card to stop
364
+ its process (and `/killall` to stop them all).
365
+
366
+ ## 🔗 Connecting to live sessions
367
+
368
+ While a turn is running, the bot marks that session busy (a `.lock` with the live
369
+ `grok` child's pid), so a second turn can't collide with it. You can still:
370
+
371
+ - **📡 Watch** — follow the running session's output live (read-only) by tailing
372
+ its event log. Stop with `/unwatch`.
373
+ - **Continue (fork)** — tapping a live session opens a **linked continuation** in
374
+ the same project, primed with the recent transcript, so you can keep
375
+ interacting from Telegram without disturbing the running turn.
376
+
377
+ Resuming an **idle** session loads it directly so you continue the exact thread.
378
+
379
+ ---
380
+
381
+ ## ⚙️ Configuration (`.env`)
382
+
383
+ | Variable | Required | Default | Description |
384
+ |---|---|---|---|
385
+ | `TELEGRAM_BOT_TOKEN` | **yes** | — | Bot token from @BotFather. |
386
+ | `ALLOWED_USERS` | recommended | *(all)* | Comma-separated Telegram user IDs. Empty = anyone (unsafe). |
387
+ | `GROK_CLI_PATH` | no | auto / `grok` | Path to the `grok` binary. |
388
+ | `GROK_WORKSPACE` | no | cwd | Default working directory. |
389
+ | `XAI_API_KEY` | no | — | xAI API key, only for headless hosts with no browser. Normally you sign in with `grok login` (or `/reauth`) — no key needed. Exported to the agent when set. |
390
+ | `GROK_MODEL` | no | `grok-4.5` | Default model for new sessions. |
391
+ | `GROK_TG_DIR` | no | `~/.grok/tg` | Folder holding this instance's `.env`, `logs/`, `data/`. Resolution: `--instance` → `GROK_TG_DIR` → a `.env` in the current folder → `~/.grok/tg`. So a `.env` created once is loaded from any startup path. |
392
+ | `GROK_AGENT` | no | — | Custom sub-agent name (informational; Grok delegates via its own `task`/`delegate` tools). |
393
+ | `GROK_TRUST_ALL_TOOLS` | no | `true` | Run tools without prompts. |
394
+ | `PROJECT_ROOTS` | no | workspace parent + home | Roots for `/projects`. |
395
+ | `STREAM_THROTTLE_MS` | no | `1500` | Live-edit interval while streaming. |
396
+ | `MESSAGE_BATCH_MS` | no | `800` | Window to coalesce rapid text messages (e.g. a long message Telegram split at 4096 chars) into one prompt. `0` disables. |
397
+ | `SHOW_TOOL_CALLS` | no | `true` | Show tool-call status messages. |
398
+ | `SHOW_EDIT_DIFFS` | no | `true` | Show unified diffs for edits. |
399
+ | `DIFF_MAX_LINES` | no | `120` | Max diff lines shown inline. |
400
+ | `DOC_MAX_CHARS` | no | `100000` | Max characters of a **text file** attachment inlined into the prompt (a long message Telegram turned into a `.txt`, plus code, logs, JSON, CSV, …). Longer files are truncated with a note; binaries are saved under `<data>/downloads` and their path is handed to the agent. `0` = unlimited. |
401
+ | `SHOW_SUBAGENTS` | no | `true` | Stream subagent (crew) start/work/finish while the main agent waits. |
402
+ | `SHOW_PROGRESS` | no | `true` | Ask the agent to append a `{progress: N%}` marker to each message; the bot parses it, hides the marker, and renders a green 0–100% bar on the live message, in session cards, and in the status panel. |
403
+ | `PROGRESS_FALLBACK` | no | `true` | When `SHOW_PROGRESS` is on but the agent emits **no** `{progress: N%}` marker (weaker/free models and long tool-heavy turns often skip it), render a **bot-computed** bar derived from real activity (completed tool calls, streamed output, elapsed time) so a live bar still advances — filling to 100% when the turn completes. The agent's own marker, when present, always takes precedence and stays monotonic. |
404
+ | `NOTIFY_OTHER_SESSIONS` | no | `true` | Deliver a session's "Done" summary (with a short created/edited/deleted count) even when it's a background session, marked "From other session". `false` keeps background sessions silent. |
405
+ | `MCP_PROBE_TIMEOUT_MS` | no | `8000` | Per-server timeout for the `/mcp` live health-check. |
406
+ | `MCP_PROBE_CONCURRENCY` | no | `6` | How many MCP health probes run at once. |
407
+ | `GROK_AUTO_RESTART` | no | `true` | Auto-restart the agent if it exits. |
408
+ | `GROK_TG_SINGLE_INSTANCE` | no | `true` | Enforce one running bot **per token**: on startup a still-alive ghost/duplicate (an old process polling Telegram with a stale `.env`, the usual cause of a phantom "⛔ Not authorized") is terminated so the fresh process wins. A manual `run` yields to an already-running background service instead of fighting it. |
409
+ | `AUTO_UPDATE` | no | `true` | Hourly check npm and, when a newer version exists **and the bot is idle** (no turn/task running, no other active Grok session), auto-update + restart + post the release notes (tagged `#update`). Global npm installs only. |
410
+ | `UPDATE_CHECK_MS` | no | `3600000` | How often to check npm for updates (ms). |
411
+ | `PROMPT_RETRY_ATTEMPTS` | no | `5` | Max retries for a transient agent error (e.g. high-traffic / `Internal error`) before any output streamed, with `6s → 12s → 24s → 48s → 60s` backoff. The real error shows each attempt; a summary after the last. `0` disables. |
412
+ | `AUTO_FORK_ON_ERROR` | no | `true` | When the retries above are exhausted on a transient error (throttle / `Internal error` / exhausted context) and nothing streamed, **logically fork** the session — open a fresh continuation primed with the recent transcript, drop the stuck session, and retry the message once. |
413
+ | `AUTO_FORK_CONTEXT_PCT` | no | `85` | When a prompt fails transiently **and** the session's last-known context usage is at/above this %, **skip the retry backoff and fork immediately** — a context-exhausted session won't recover by retrying the same oversized prompt (throttling on a near-full session shows up as `-32603 … throttled`). Forking compacts it into a fresh continuation primed with the recent transcript. Requires `AUTO_FORK_ON_ERROR`; `0` disables this trigger. |
414
+ | `RESUME_ON_STREAM_ERROR` | no | `true` | When a transient error (throttle / `Internal error` / dropped response stream) strikes **after the reply already began streaming**, the retry/fork/rotate paths above are skipped (re-sending would re-run tools that already executed). Instead the bot asks the **same session to continue** from where it stopped — the partial reply and completed tool results are already in history, so nothing is repeated — using the same backoff so the throttle can clear. Skipped for context-full sessions (they can't recover by continuing). |
415
+ | `LOG_LEVEL` | no | `info` | `debug` \| `info` \| `warn` \| `error`. |
416
+ | `LOG_DIR` / `LOG_FILE` | no | `<project>/logs/…` | Log location. |
417
+
418
+ ---
419
+
420
+ ## 🧩 How it works
421
+
422
+ ```
423
+ Telegram ──HTTPS──▶ Bot (grammY)
424
+ │ spawns once
425
+
426
+ grok agent stdio ◀── JSON-RPC 2.0 over stdio (ACP) ──▶ Bot
427
+
428
+ ├─ initialize / authenticate (cached login / API key)
429
+ ├─ session/new · session/load (projects, resume)
430
+ ├─ session/prompt (your messages)
431
+ └─ session/update (streamed text, tools)
432
+ ```
433
+
434
+ One `grok agent stdio` process multiplexes many sessions. After `initialize` the
435
+ bot runs `authenticate` (using the cached `grok login` token, or `XAI_API_KEY`),
436
+ then streamed `agent_message_chunk` updates are assembled into a live, throttled
437
+ message and `tool_call` updates render as status lines with diffs.
438
+
439
+ The bot records the sessions **it** drives on disk under `<data>/sessions/`:
440
+ `<id>.json` (metadata), `<id>.jsonl` (history, used by `/history` and live
441
+ watch), and `<id>.lock` (written while a turn runs, for active detection). This
442
+ layout is entirely separate from any Kiro bridge, so the two never collide.
443
+
444
+ ---
445
+
446
+ ## 📁 Project layout
447
+
448
+ ```
449
+ src/
450
+ ├── index.ts Entry point, daemon-friendly logging, shutdown
451
+ ├── cli.ts CLI: run / install / start / stop / status / logs
452
+ ├── config.ts .env loading, paths, daemon options
453
+ ├── logger.ts Leveled logger with file output
454
+ ├── grok/ Grok bridge: headless client, JSONL types, models, session log
455
+ ├── sessions/ Session discovery, history parser, live tail watcher
456
+ ├── projects/ Project directory discovery
457
+ ├── mcp/ MCP config (list/toggle) + live health probe
458
+ ├── render/ Markdown→MarkdownV2, diffs, tool formatting, chunking
459
+ ├── stream/ Incremental edit-streaming
460
+ ├── service/ Cross-platform daemon (windows/linux/macos + selector)
461
+ └── bot/ grammY bot, per-chat runtime, handlers
462
+ ```
463
+
464
+ ---
465
+
466
+ ## ❓ FAQ
467
+
468
+ **Can I run the Grok Telegram bot 24/7 on a server?** Yes — `npm run install:service`
469
+ installs a user-level service (systemd/launchd/Scheduled Task) that starts on
470
+ boot and auto-restarts on crash.
471
+
472
+ **How do I control Grok from my phone?** Set up the bot, message it on Telegram,
473
+ and pick a project with `/projects`. Every message becomes a Grok prompt.
474
+
475
+ **Can multiple people use one bot?** Add their IDs to `ALLOWED_USERS`. Each chat
476
+ gets its own session.
477
+
478
+ **Why can't I take over a session that's already running?** Grok locks active
479
+ sessions exclusively. The bot lets you **watch** it live or **fork** a linked
480
+ continuation instead. See "Connecting to live sessions".
481
+
482
+ **Does it support custom agents and MCP servers?** Yes — set `GROK_AGENT`, and
483
+ the bot inherits whatever MCP servers Grok CLI is configured with.
484
+
485
+ ---
486
+
487
+ ## 🔐 Tool approvals
488
+
489
+ Over ACP, Grok honors a permission mode. With `GROK_TRUST_ALL_TOOLS=true`
490
+ (default) the bot passes `--always-approve`, so tools run without prompts. Set it
491
+ to `false` to run in ACP **"ask"** mode: Grok sends `session/request_permission`
492
+ before risky tools (file writes, shell commands) and the bot surfaces
493
+ **Approve / Approve always / Deny** buttons in Telegram, sending your choice back
494
+ (unanswered prompts eventually cancel). You can also intervene on any live turn
495
+ with the tool stream + **⏹ Stop** (`/cancel`), which cancels that session's turn.
496
+
497
+ ## 🔐 Security
498
+
499
+ This bot lets authorized Telegram users run commands and edit files on the host.
500
+ **Always set `ALLOWED_USERS`**, keep `.env` private, and run as a non-privileged
501
+ user. See [SECURITY.md](./SECURITY.md) for the full model.
502
+
503
+ ---
504
+
505
+ ## 🗺 Roadmap
506
+
507
+ - [x] Projects, resume & attach to live sessions
508
+ - [x] Queued follow-ups, edit diffs, quality MarkdownV2
509
+ - [x] Persistent menu + live status panel (project / agent / reasoning / model)
510
+ - [x] Scheduled tasks (once / daily / weekly / monthly / interval)
511
+ - [x] Multi-image prompts (albums)
512
+ - [x] Combined, throttled output (anti-spam)
513
+ - [x] 24/7 cross-platform background service
514
+ - [x] Voice messages → speech-to-text → prompt (multi-language)
515
+ - [x] Context-usage % in the status panel
516
+ - [x] Inline approvals — approve/deny risky tools from buttons (non trust-all mode)
517
+ - [x] Account & context usage (`/usage`)
518
+ - [x] Multiple accounts with one-tap switch + auto-rotate on errors (`/accounts`)
519
+ - [x] Organization / Import-from-Grok-IDE login + credits on the Done line
520
+ - [x] Release automation — downloadable zip + CHANGELOG-driven notes on tag push
521
+ - [x] README community sections — Contributors, Top Contributors, Stars, StarMapper
522
+ - [ ] **Token & cost meter** — per-session token counts and an estimated spend tally
523
+ - [ ] **Text-to-speech replies** — optionally speak answers back as voice notes
524
+ - [ ] **Scheduled-task chaining & conditions** — run task B after A, or only if a command/file check passes
525
+ - [ ] **Team mode** — multiple authorized users with per-user sessions, roles, and an audit log
526
+ - [ ] Localized bot UI (i18n)
527
+ - [ ] Docker image with `grok` preinstalled
528
+ - [ ] Webhook mode for serverless deployment
529
+
530
+ Have an idea? Open a [feature request](../../issues/new/choose).
531
+
532
+ ## 🤝 Contributing
533
+
534
+ Contributions are very welcome! See **[CONTRIBUTING.md](./CONTRIBUTING.md)** to get
535
+ started — no build step is required (`npm run dev`), and `npm run typecheck` must
536
+ pass.
537
+
538
+ New here? Look for issues labeled
539
+ [**good first issue**](../../issues?q=is%3Aopen+label%3A%22good+first+issue%22)
540
+ and [**help wanted**](../../issues?q=is%3Aopen+label%3A%22help+wanted%22).
541
+
542
+ By participating you agree to the [Code of Conduct](./CODE_OF_CONDUCT.md).
543
+
544
+ ---
545
+
546
+ ## 👥 Contributors
547
+
548
+ [![Contributors](https://contrib.rocks/image?repo=artickc/grok-telegram-bot&max=100&columns=20&anon=1)](https://github.com/artickc/grok-telegram-bot/graphs/contributors)
549
+
550
+ ### How to Contribute
551
+
552
+ 1. Fork the repository
553
+ 2. Create your feature branch (`git checkout -b feat/amazing-feature`)
554
+ 3. Commit your changes (`git commit -m 'Add amazing feature'`)
555
+ 4. Push to the branch (`git push origin feat/amazing-feature`)
556
+ 5. Open a Pull Request
557
+
558
+ See [CONTRIBUTING.md](./CONTRIBUTING.md) for detailed guidelines.
559
+
560
+ ### Releasing a New Version
561
+
562
+ ```bash
563
+ # Bump the version, update CHANGELOG.md, then push a tag.
564
+ # The release workflow builds a downloadable zip and publishes notes automatically.
565
+ npm version minor # or: patch / major — updates package.json + commits
566
+ git push --follow-tags # pushing the v* tag triggers .github/workflows/release.yml
567
+ ```
568
+
569
+ ---
570
+
571
+ ## ⭐ Top Contributors
572
+
573
+ > This project is built and maintained in the open. These people have made the
574
+ > contributions that shape its quality, stability, and reach. **Thank you.**
575
+
576
+ <table>
577
+ <tr>
578
+ <td align="center" width="180">
579
+ <a href="https://github.com/artickc">
580
+ <img src="https://github.com/artickc.png?size=100" width="80" height="80" style="border-radius:50%" alt="artickc"/><br/>
581
+ <sub><b>artickc</b></sub>
582
+ </a><br/>
583
+ 🥇 Maintainer<br/>
584
+ <sub>Created the bot: Grok headless bridge, multi-session<br/>runtime, scheduler, daemon &amp; renderer</sub>
585
+ </td>
586
+ </tr>
587
+ </table>
588
+
589
+ > 🙏 Every pull request, bug report, and idea matters. Open source is built by
590
+ > people like them — see the full list under [Contributors](#-contributors).
591
+
592
+ ---
593
+
594
+ ## 📊 Stars
595
+
596
+ <a href="https://www.star-history.com/?repos=artickc%2Fgrok-telegram-bot&type=date&legend=top-left">
597
+ <picture>
598
+ <source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=artickc/grok-telegram-bot&type=Date&theme=dark&legend=top-left" />
599
+ <source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=artickc/grok-telegram-bot&type=Date&legend=top-left" />
600
+ <img alt="Star History Chart" src="https://api.star-history.com/svg?repos=artickc/grok-telegram-bot&type=Date&legend=top-left" />
601
+ </picture>
602
+ </a>
603
+
604
+ If this project helps you, please consider giving it a ⭐ — it really helps!
605
+
606
+ ---
607
+
608
+ ## 🌍 StarMapper
609
+
610
+ > See where in the world this project's stargazers live — an interactive map of
611
+ > the community.
612
+
613
+ <a href="https://starmapper.bruniaux.com/artickc/grok-telegram-bot">
614
+ <picture>
615
+ <source media="(prefers-color-scheme: dark)" srcset="https://starmapper.bruniaux.com/api/map-image/artickc/grok-telegram-bot?theme=dark" />
616
+ <source media="(prefers-color-scheme: light)" srcset="https://starmapper.bruniaux.com/api/map-image/artickc/grok-telegram-bot?theme=light" />
617
+ <img alt="StarMapper — where this project's stargazers live" src="https://starmapper.bruniaux.com/api/map-image/artickc/grok-telegram-bot" />
618
+ </picture>
619
+ </a>
620
+
621
+ ---
622
+
623
+ ## 📦 Download & Releases
624
+
625
+ Grab the latest packaged build from the
626
+ [**Releases**](https://github.com/artickc/grok-telegram-bot/releases) page — each
627
+ release ships a clean `grok-telegram-bot-<version>.zip` (no `node_modules` or
628
+ secrets) plus GitHub's source archives. See [CHANGELOG.md](./CHANGELOG.md) for
629
+ what changed in each version, **[docs/INSTALL.md](./docs/INSTALL.md)** for the
630
+ full 1-click install guide, and **[docs/UPGRADE.md](./docs/UPGRADE.md)** for how
631
+ to update an existing install (npm, zip, or source).
632
+
633
+ ---
634
+
635
+ ## 📄 License
636
+
637
+ [MIT](./LICENSE) — see also [CONTRIBUTING](./CONTRIBUTING.md) and
638
+ [Code of Conduct](./CODE_OF_CONDUCT.md).
639
+
640
+ ---
641
+
642
+ <sub>Keywords: Grok CLI Telegram bot, xAI Grok coding agent, AI coding
643
+ assistant on Telegram, mobile AI pair programming, remote coding agent, run AI
644
+ agent as a service, Windows/Linux/macOS daemon, ChatOps for developers.</sub>
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * `grok-tg` launcher — runs the TypeScript CLI through the tsx loader so the
4
+ * project needs no build step.
5
+ */
6
+ import { spawnSync } from "node:child_process";
7
+ import { dirname, join } from "node:path";
8
+ import { fileURLToPath } from "node:url";
9
+
10
+ const root = join(dirname(fileURLToPath(import.meta.url)), "..");
11
+ const cli = join(root, "src", "cli.ts");
12
+
13
+ const result = spawnSync(process.execPath, ["--import", "tsx", cli, ...process.argv.slice(2)], {
14
+ stdio: "inherit",
15
+ cwd: root,
16
+ // Run the code from the package dir (so `tsx` + sources resolve), but tell the
17
+ // bot to keep its .env/logs/data in the user's actual working directory.
18
+ env: { ...process.env, GROK_TG_CWD: process.env.GROK_TG_CWD || process.cwd() },
19
+ });
20
+
21
+ process.exit(result.status ?? 0);