clawless 0.1.2

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 ADDED
@@ -0,0 +1,404 @@
1
+ # Telegram-Gemini ACP Bridge
2
+
3
+ A bridge that connects a Telegram bot to the Gemini CLI using the Agent Communication Protocol (ACP). This turns Telegram into a "remote terminal" for your local Gemini agent, enabling rich tool use and persistent context.
4
+
5
+ ## Features
6
+
7
+ - 🤖 **Telegram Bot Interface**: Interact with Gemini CLI through Telegram
8
+ - ⌨️ **Typing Status UX**: Shows Telegram typing indicator while Gemini is processing
9
+ - 🛠️ **Rich Tool Support**: Leverages MCP (Model Context Protocol) servers connected to Gemini CLI
10
+ - 🔒 **Privacy**: Runs on your hardware, you control data flow
11
+ - 💾 **Persistent Context**: Maintains local session unlike standard API calls
12
+ - 📬 **Sequential Queueing**: Processes one message at a time to avoid overlap and races
13
+ - 🔔 **Local Callback Endpoint**: Accepts localhost HTTP POST requests and forwards payloads directly to Telegram
14
+ - ⏰ **Cron Scheduler**: Schedule tasks to run at specific times or on recurring basis via REST API
15
+
16
+ ## Architecture
17
+
18
+ ```
19
+ ┌──────────┐ ┌───────────┐ ┌─────────────┐
20
+ │ Telegram │ ◄─────► │ Bridge │ ◄─────► │ Gemini CLI │
21
+ │ User │ │ (Node.js) │ ACP │ (Local) │
22
+ └──────────┘ └───────────┘ └─────────────┘
23
+ ```
24
+
25
+ The bridge:
26
+ 1. Receives messages from Telegram users
27
+ 2. Forwards them to the Gemini CLI via ACP (Agent Communication Protocol)
28
+ 3. Shows typing status, then sends a single final response
29
+
30
+ ## Prerequisites
31
+
32
+ - **Node.js** 18.0.0 or higher
33
+ - **Gemini CLI** installed and configured with ACP support
34
+ - **Telegram Bot Token** from [@BotFather](https://t.me/BotFather)
35
+
36
+ ## Installation
37
+
38
+ 1. Install dependencies:
39
+ ```bash
40
+ npm install
41
+ ```
42
+
43
+ 2. Configure environment variables:
44
+ ```bash
45
+ cp .env.example .env
46
+ ```
47
+
48
+ Edit `.env` and add your Telegram bot token:
49
+ ```env
50
+ TELEGRAM_TOKEN=your_bot_token_here
51
+ TYPING_INTERVAL_MS=4000
52
+ GEMINI_TIMEOUT_MS=900000
53
+ GEMINI_NO_OUTPUT_TIMEOUT_MS=60000
54
+ ACP_STREAM_STDOUT=false
55
+ ACP_DEBUG_STREAM=false
56
+ ```
57
+
58
+ ## Getting a Telegram Bot Token
59
+
60
+ 1. Open Telegram and search for [@BotFather](https://t.me/BotFather)
61
+ 2. Send `/newbot` command
62
+ 3. Follow the prompts to create your bot
63
+ 4. Copy the token provided by BotFather
64
+ 5. Paste it into your `.env` file
65
+
66
+ ## Usage
67
+
68
+ ### CLI Mode
69
+
70
+ After install, the package exposes a CLI command:
71
+
72
+ ```bash
73
+ clawless
74
+ ```
75
+
76
+ Local development alternatives:
77
+
78
+ ```bash
79
+ npm run cli
80
+ npx clawless
81
+ ```
82
+
83
+ ### Config File (CLI)
84
+
85
+ On first run, the CLI automatically creates:
86
+
87
+ ```text
88
+ ~/.clawless/config.json
89
+ ```
90
+
91
+ with placeholder values, then exits so you can edit it.
92
+
93
+ After updating placeholders, run again:
94
+
95
+ ```bash
96
+ clawless
97
+ ```
98
+
99
+ You can also use a custom path:
100
+
101
+ ```bash
102
+ clawless --config /path/to/config.json
103
+ ```
104
+
105
+ If the custom config path does not exist, a template file is created there as well.
106
+
107
+ You can still bootstrap from the example file if preferred:
108
+
109
+ ```bash
110
+ cp clawless.config.example.json ~/.clawless/config.json
111
+ ```
112
+
113
+ Environment variables still work and take precedence over config values.
114
+
115
+ ### Run In Background
116
+
117
+ Simple background run:
118
+
119
+ ```bash
120
+ nohup clawless > clawless.log 2>&1 &
121
+ ```
122
+
123
+ Recommended for production: PM2 (see section below).
124
+
125
+ ### Development Mode
126
+
127
+ ```bash
128
+ npm run dev
129
+ ```
130
+
131
+ This runs the bot with Node.js watch mode for automatic restarts on file changes.
132
+
133
+ ### Production Mode
134
+
135
+ ```bash
136
+ npm start
137
+ ```
138
+
139
+ ### Using PM2 (Recommended for Production)
140
+
141
+ PM2 keeps your bridge running continuously and restarts it automatically if it crashes.
142
+
143
+ 1. Install PM2 globally:
144
+ ```bash
145
+ npm install -g pm2
146
+ ```
147
+
148
+ 2. Start the bridge:
149
+ ```bash
150
+ pm2 start ecosystem.config.json
151
+ ```
152
+
153
+ PM2 will automatically create the `logs/` directory for log files.
154
+
155
+ 3. View logs:
156
+ ```bash
157
+ pm2 logs clawless
158
+ ```
159
+
160
+ 4. Manage the process:
161
+ ```bash
162
+ pm2 status # View status
163
+ pm2 restart clawless # Restart
164
+ pm2 stop clawless # Stop
165
+ pm2 delete clawless # Remove from PM2
166
+ ```
167
+
168
+ 5. Set up auto-start on system boot:
169
+ ```bash
170
+ pm2 startup
171
+ pm2 save
172
+ ```
173
+
174
+ ## Configuration
175
+
176
+ ### Environment Variables
177
+
178
+ | Variable | Required | Default | Description |
179
+ |----------|----------|---------|-------------|
180
+ | `TELEGRAM_TOKEN` | Yes | - | Your Telegram bot token from BotFather |
181
+ | `TYPING_INTERVAL_MS` | No | 4000 | Interval (in milliseconds) for refreshing Telegram typing status |
182
+ | `GEMINI_TIMEOUT_MS` | No | 900000 | Overall timeout for a single Gemini CLI run |
183
+ | `GEMINI_NO_OUTPUT_TIMEOUT_MS` | No | 60000 | Idle timeout; aborts if Gemini emits no output for this duration |
184
+ | `GEMINI_KILL_GRACE_MS` | No | 5000 | Grace period after SIGTERM before escalating Gemini child process shutdown to SIGKILL |
185
+ | `GEMINI_APPROVAL_MODE` | No | yolo | Gemini approval mode (for example: `default`, `auto_edit`, `yolo`, `plan`) |
186
+ | `GEMINI_MODEL` | No | - | Gemini model override passed to CLI |
187
+ | `ACP_PERMISSION_STRATEGY` | No | allow_once | Auto-select ACP permission option kind (`allow_once`, `reject_once`, or `cancelled`) |
188
+ | `ACP_STREAM_STDOUT` | No | false | Writes raw ACP text chunks to stdout as they arrive |
189
+ | `ACP_DEBUG_STREAM` | No | false | Writes structured ACP chunk timing/count debug logs |
190
+ | `MAX_RESPONSE_LENGTH` | No | 4000 | Maximum response length in characters to prevent memory issues |
191
+ | `HEARTBEAT_INTERVAL_MS` | No | 60000 | Server heartbeat log interval in milliseconds (`0` disables heartbeat logs) |
192
+ | `CALLBACK_HOST` | No | 127.0.0.1 | Bind address for callback server |
193
+ | `CALLBACK_PORT` | No | 8788 | Bind port for callback server |
194
+ | `CALLBACK_AUTH_TOKEN` | No | - | Optional bearer/token guard for callback endpoint |
195
+ | `CALLBACK_MAX_BODY_BYTES` | No | 65536 | Maximum accepted callback request body size |
196
+ | `AGENT_BRIDGE_HOME` | No | ~/.clawless | Home directory for Gemini Bridge runtime files |
197
+ | `MEMORY_FILE_PATH` | No | ~/.clawless/MEMORY.md | Persistent memory file path injected into Gemini prompt context |
198
+ | `MEMORY_MAX_CHARS` | No | 12000 | Max memory-file characters injected into prompt context |
199
+ | `SCHEDULES_FILE_PATH` | No | ~/.clawless/schedules.json | Persistent scheduler storage file |
200
+
201
+ ### Local Callback Endpoint
202
+
203
+ The bridge exposes:
204
+
205
+ - `POST http://127.0.0.1:8788/callback/telegram` - Send messages to Telegram
206
+ - `GET http://127.0.0.1:8788/healthz` - Health check
207
+ - `POST/GET/DELETE http://127.0.0.1:8788/api/schedule`, `GET http://127.0.0.1:8788/api/schedule/:id` - Scheduler API
208
+
209
+ Request body for callback:
210
+
211
+ ```json
212
+ {
213
+ "text": "Nightly job finished successfully"
214
+ }
215
+ ```
216
+
217
+ - `chatId` is optional. If omitted, the bridge sends to a persisted chat binding learned from inbound Telegram messages.
218
+ - To bind once, send any message to the bot from your target chat.
219
+ - If `CALLBACK_AUTH_TOKEN` is set, send either `x-callback-token: <token>` or `Authorization: Bearer <token>`.
220
+
221
+ Cron-friendly example:
222
+
223
+ ```bash
224
+ curl -sS -X POST "http://127.0.0.1:8788/callback/telegram" \
225
+ -H "Content-Type: application/json" \
226
+ -H "x-callback-token: $CALLBACK_AUTH_TOKEN" \
227
+ -d '{"text":"Backup completed at 03:00"}'
228
+ ```
229
+
230
+ ### Scheduler API
231
+
232
+ The bridge includes a built-in cron scheduler that allows you to schedule tasks to be executed through Gemini CLI:
233
+
234
+ - Schedules are persisted to disk and automatically reloaded on restart.
235
+ - Default storage path: `~/.clawless/schedules.json` (override with `SCHEDULES_FILE_PATH`).
236
+
237
+ **Create a recurring schedule:**
238
+ ```bash
239
+ curl -X POST http://127.0.0.1:8788/api/schedule \
240
+ -H "Content-Type: application/json" \
241
+ -d '{
242
+ "message": "Check my calendar and send me a summary",
243
+ "description": "Daily calendar summary",
244
+ "cronExpression": "0 9 * * *"
245
+ }'
246
+ ```
247
+
248
+ **Create a one-time schedule:**
249
+ ```bash
250
+ curl -X POST http://127.0.0.1:8788/api/schedule \
251
+ -H "Content-Type: application/json" \
252
+ -d '{
253
+ "message": "Remind me to take a break",
254
+ "oneTime": true,
255
+ "runAt": "2026-02-13T15:30:00Z"
256
+ }'
257
+ ```
258
+
259
+ When a scheduled job runs, it executes the message through Gemini CLI and sends the response to your Telegram chat.
260
+
261
+ **Ask Gemini to create schedules naturally:**
262
+ - "Remind me to take a break in 30 minutes"
263
+ - "Check my calendar every morning at 9am and send me a summary"
264
+ - "Every Friday at 5pm, remind me to review my weekly goals"
265
+
266
+ See [SCHEDULER.md](SCHEDULER.md) for complete API documentation.
267
+
268
+ ### Persistent Memory File
269
+
270
+ - The bridge ensures a memory file exists at `~/.clawless/MEMORY.md` on startup.
271
+ - Gemini is started with include access to both `~/.clawless` and your full home directory (`~/`).
272
+ - ACP session setup uses the required `mcpServers` field with an empty array and relies on Gemini CLI runtime defaults for MCP/skills loading.
273
+ - Each prompt includes memory instructions and current `MEMORY.md` content.
274
+ - When asked to memorize/remember something, Gemini is instructed to append new notes under `## Notes`.
275
+
276
+ ### Timeout Tuning
277
+
278
+ Use both timeouts together for reliability:
279
+
280
+ - `GEMINI_TIMEOUT_MS`: hard cap for total request time (recommended: `900000`)
281
+ - `GEMINI_NO_OUTPUT_TIMEOUT_MS`: fail fast if output stalls (recommended: `60000`)
282
+ - Set `GEMINI_NO_OUTPUT_TIMEOUT_MS=0` to disable idle timeout
283
+
284
+ ### Response Length Limit
285
+
286
+ The `MAX_RESPONSE_LENGTH` prevents memory issues with very long responses:
287
+
288
+ - **Default**: 4000 characters (Telegram's limit is 4096 per message)
289
+ - Responses exceeding this limit are truncated with a notification
290
+ - Protects against unbounded memory growth
291
+
292
+ ## How It Works
293
+
294
+ ### The Logic Flow
295
+
296
+ 1. **User sends a message** via Telegram
297
+ 2. **Bridge queues** the message if another request is in progress
298
+ 3. **Worker dequeues** the next message when prior processing completes
299
+ 4. **Gemini run starts** and typing status is shown in Telegram
300
+ 5. **Single final reply** is sent when Gemini finishes
301
+
302
+ ### Queueing Behavior
303
+
304
+ The bridge uses a single-worker in-memory queue:
305
+ - Prevents overlapping Gemini runs
306
+ - Preserves message order
307
+ - Avoids duplicate-edit/fallback races from message updates
308
+
309
+ ## Advantages Over Standard API Bots
310
+
311
+ 1. **Persistent Context**: The Gemini CLI maintains a local session, unlike stateless API calls
312
+ 2. **Local File Access**: Can access files on your server if configured
313
+ 3. **MCP Tool Integration**: Automatically uses tools from connected MCP servers (Calendar, Database, etc.)
314
+ 4. **Privacy Control**: Runs on your hardware, you control data processing
315
+ 5. **Custom Configuration**: Use your specific Gemini CLI setup and preferences
316
+
317
+ ## Troubleshooting
318
+
319
+ ### Bot doesn't respond
320
+
321
+ 1. Check if Gemini CLI is installed:
322
+ ```bash
323
+ which gemini
324
+ ```
325
+
326
+ 2. Verify Gemini CLI supports ACP:
327
+ ```bash
328
+ gemini --help | grep acp
329
+ ```
330
+
331
+ 3. Check bot logs for errors
332
+
333
+ ### Rate limit errors
334
+
335
+ If you see "429 Too Many Requests" errors:
336
+ 1. Increase `TYPING_INTERVAL_MS` in `.env` (try 5000 or higher)
337
+ 2. Restart the bot
338
+
339
+ ### Connection issues
340
+
341
+ 1. Verify your internet connection
342
+ 2. Check if Telegram API is accessible
343
+ 3. Ensure `TELEGRAM_TOKEN` is correct in `.env`
344
+
345
+ ## Development
346
+
347
+ ### Project Structure
348
+
349
+ ```
350
+ RemoteAgent/
351
+ ├── index.ts # Main bridge application
352
+ ├── messaging/
353
+ │ └── telegramClient.ts # Telegram adapter implementing neutral message context
354
+ ├── package.json # Node.js dependencies
355
+ ├── ecosystem.config.json # PM2 configuration
356
+ ├── .env.example # Environment variables template
357
+ ├── .env # Your local configuration (not in git)
358
+ └── README.md # This file
359
+ ```
360
+
361
+ ### Adding Features
362
+
363
+ The codebase is designed to be simple and extensible:
364
+ - Core queue + ACP logic is in `index.ts`
365
+ - Messaging-platform specifics live in `messaging/telegramClient.ts`
366
+ - New bot platforms can implement the same message context shape (`text`, `startTyping()`, `sendText()`)
367
+ - Error handling is centralized
368
+ - Rate limiting logic is configurable
369
+
370
+ ## Security Considerations
371
+
372
+ - **Never commit** `.env` file with your token (it's in `.gitignore`)
373
+ - **Rotate tokens** if accidentally exposed
374
+ - **Limit bot access** using Telegram's bot settings
375
+ - **Monitor logs** for unusual activity
376
+
377
+ ## Contributing
378
+
379
+ Contributions are welcome! Please:
380
+ 1. Fork the repository
381
+ 2. Create a feature branch
382
+ 3. Make your changes
383
+ 4. Submit a pull request
384
+
385
+ ## License
386
+
387
+ MIT License - see [LICENSE](LICENSE) file for details
388
+
389
+ ## Credits
390
+
391
+ Built with:
392
+ - [Telegraf](https://telegraf.js.org/) - Telegram Bot framework
393
+ - [@agentclientprotocol/sdk](https://www.npmjs.com/package/@agentclientprotocol/sdk) - Agent Communication Protocol SDK
394
+
395
+ ## Support
396
+
397
+ For issues and questions:
398
+ - Open an issue on GitHub
399
+ - Check existing issues for solutions
400
+ - Review Gemini CLI documentation
401
+
402
+ ---
403
+
404
+ **Note**: This bridge requires a working Gemini CLI installation with ACP support. Ensure your CLI is properly configured before running the bridge.
package/SCHEDULER.md ADDED
@@ -0,0 +1,255 @@
1
+ # Scheduler API Documentation
2
+
3
+ The Clawless now includes a cron scheduler API that allows you to schedule tasks to be executed through Gemini CLI at specific times or on a recurring basis.
4
+
5
+ ## Overview
6
+
7
+ When a scheduled job runs:
8
+ 1. The scheduled message is sent to a standalone Gemini CLI session
9
+ 2. Gemini processes the message and generates a response
10
+ 3. The response is sent back to your Telegram bot
11
+ 4. The result appears in your Telegram chat
12
+
13
+ Schedules are persisted to disk and reloaded on startup. By default the file is `~/.clawless/schedules.json` and can be overridden via `SCHEDULES_FILE_PATH`.
14
+
15
+ ## API Endpoints
16
+
17
+ All scheduler endpoints are available at `http://127.0.0.1:8788/api/schedule`
18
+
19
+ ### Authentication
20
+
21
+ If `CALLBACK_AUTH_TOKEN` is set in your configuration, include it in your requests:
22
+ - Header: `x-callback-token: <your-token>`
23
+ - Or: `Authorization: Bearer <your-token>`
24
+
25
+ ### Create a Schedule
26
+
27
+ **POST** `/api/schedule`
28
+
29
+ Create a new recurring or one-time schedule.
30
+
31
+ #### Recurring Schedule Example
32
+
33
+ ```bash
34
+ curl -X POST http://127.0.0.1:8788/api/schedule \
35
+ -H "Content-Type: application/json" \
36
+ -d '{
37
+ "message": "Check my calendar and send me a summary",
38
+ "description": "Daily calendar summary",
39
+ "cronExpression": "0 9 * * *"
40
+ }'
41
+ ```
42
+
43
+ **Request Body:**
44
+ ```json
45
+ {
46
+ "message": "The prompt to send to Gemini CLI",
47
+ "description": "Optional description of the schedule",
48
+ "cronExpression": "0 9 * * *"
49
+ }
50
+ ```
51
+
52
+ **Cron Expression Format:**
53
+ ```
54
+ * * * * *
55
+ │ │ │ │ │
56
+ │ │ │ │ └─ Day of week (0-7, both 0 and 7 are Sunday)
57
+ │ │ │ └─── Month (1-12)
58
+ │ │ └───── Day of month (1-31)
59
+ │ └─────── Hour (0-23)
60
+ └───────── Minute (0-59)
61
+ ```
62
+
63
+ **Common Cron Examples:**
64
+ - `0 9 * * *` - Daily at 9:00 AM
65
+ - `0 */6 * * *` - Every 6 hours
66
+ - `*/30 * * * *` - Every 30 minutes
67
+ - `0 9 * * 1-5` - Weekdays at 9:00 AM
68
+ - `0 0 1 * *` - First day of every month at midnight
69
+
70
+ #### One-Time Schedule Example
71
+
72
+ ```bash
73
+ curl -X POST http://127.0.0.1:8788/api/schedule \
74
+ -H "Content-Type: application/json" \
75
+ -d '{
76
+ "message": "Remind me to take a break",
77
+ "description": "Break reminder",
78
+ "oneTime": true,
79
+ "runAt": "2026-02-13T15:30:00Z"
80
+ }'
81
+ ```
82
+
83
+ **Request Body:**
84
+ ```json
85
+ {
86
+ "message": "The prompt to send to Gemini CLI",
87
+ "description": "Optional description",
88
+ "oneTime": true,
89
+ "runAt": "2026-02-13T15:30:00Z"
90
+ }
91
+ ```
92
+
93
+ **Response:**
94
+ ```json
95
+ {
96
+ "ok": true,
97
+ "schedule": {
98
+ "id": "schedule_1707835800000_abc123",
99
+ "message": "Check my calendar and send me a summary",
100
+ "description": "Daily calendar summary",
101
+ "cronExpression": "0 9 * * *",
102
+ "oneTime": false,
103
+ "createdAt": "2026-02-13T10:00:00.000Z",
104
+ "active": true
105
+ }
106
+ }
107
+ ```
108
+
109
+ ### List Schedules
110
+
111
+ **GET** `/api/schedule`
112
+
113
+ List all active schedules.
114
+
115
+ ```bash
116
+ curl http://127.0.0.1:8788/api/schedule
117
+ ```
118
+
119
+ **Response:**
120
+ ```json
121
+ {
122
+ "ok": true,
123
+ "schedules": [
124
+ {
125
+ "id": "schedule_1707835800000_abc123",
126
+ "message": "Check my calendar",
127
+ "description": "Daily calendar summary",
128
+ "cronExpression": "0 9 * * *",
129
+ "oneTime": false,
130
+ "createdAt": "2026-02-13T10:00:00.000Z",
131
+ "active": true,
132
+ "lastRun": "2026-02-13T09:00:00.000Z"
133
+ }
134
+ ]
135
+ }
136
+ ```
137
+
138
+ ### Get a Specific Schedule
139
+
140
+ **GET** `/api/schedule/:id`
141
+
142
+ Get details of a specific schedule.
143
+
144
+ ```bash
145
+ curl http://127.0.0.1:8788/api/schedule/schedule_1707835800000_abc123
146
+ ```
147
+
148
+ **Response:**
149
+ ```json
150
+ {
151
+ "ok": true,
152
+ "schedule": {
153
+ "id": "schedule_1707835800000_abc123",
154
+ "message": "Check my calendar",
155
+ "description": "Daily calendar summary",
156
+ "cronExpression": "0 9 * * *",
157
+ "oneTime": false,
158
+ "createdAt": "2026-02-13T10:00:00.000Z",
159
+ "active": true,
160
+ "lastRun": "2026-02-13T09:00:00.000Z"
161
+ }
162
+ }
163
+ ```
164
+
165
+ ### Delete a Schedule
166
+
167
+ **DELETE** `/api/schedule/:id`
168
+
169
+ Remove a schedule. This stops any future executions.
170
+
171
+ ```bash
172
+ curl -X DELETE http://127.0.0.1:8788/api/schedule/schedule_1707835800000_abc123
173
+ ```
174
+
175
+ **Response:**
176
+ ```json
177
+ {
178
+ "ok": true,
179
+ "message": "Schedule removed"
180
+ }
181
+ ```
182
+
183
+ ## Using with Gemini CLI
184
+
185
+ The Gemini CLI is aware of the scheduler API through the system prompt. You can ask Gemini to create schedules naturally:
186
+
187
+ **Examples:**
188
+
189
+ 1. **"Remind me to take a break in 30 minutes"**
190
+ - Gemini will create a one-time schedule
191
+
192
+ 2. **"Check my calendar every morning at 9am and send me a summary"**
193
+ - Gemini will create a recurring schedule with cron expression `0 9 * * *`
194
+
195
+ 3. **"Every Friday at 5pm, remind me to review my weekly goals"**
196
+ - Gemini will create a recurring schedule with cron expression `0 17 * * 5`
197
+
198
+ 4. **"List my scheduled tasks"**
199
+ - Gemini will query the schedule API and show you all active schedules
200
+
201
+ 5. **"Cancel the calendar summary schedule"**
202
+ - Gemini will find and delete the matching schedule
203
+
204
+ ## How It Works
205
+
206
+ 1. When you ask Gemini to create a schedule, it will:
207
+ - Parse your request to determine timing (cron expression or specific date/time)
208
+ - Call the scheduler API with appropriate parameters
209
+ - Confirm the schedule was created
210
+
211
+ 2. When the scheduled time arrives:
212
+ - The scheduler executes the job
213
+ - The message is sent to a new Gemini CLI session
214
+ - Gemini processes the message (can use tools, access files, etc.)
215
+ - The response is sent to your Telegram chat
216
+
217
+ 3. For recurring schedules:
218
+ - The job runs according to the cron expression
219
+ - Each execution is independent
220
+ - The schedule continues until deleted
221
+
222
+ 4. For one-time schedules:
223
+ - The job runs once at the specified time
224
+ - The schedule is automatically deleted after execution
225
+
226
+ ## Notes
227
+
228
+ - Schedules are stored in memory and will be lost if the bridge restarts
229
+ - Make sure your Telegram bot has received at least one message so it knows where to send results
230
+ - The timezone used for cron schedules is determined by the `TZ` environment variable (defaults to UTC)
231
+ - Scheduled jobs run in separate Gemini CLI sessions, so they have access to all configured tools and MCP servers
232
+
233
+ ## Troubleshooting
234
+
235
+ ### Schedule not executing
236
+ - Check the bridge logs for error messages
237
+ - Verify the cron expression is valid using a cron expression tester
238
+ - Ensure the bridge is running continuously
239
+
240
+ ### Results not appearing in Telegram
241
+ - Send at least one message to your bot first to establish the chat binding
242
+ - Check if `lastIncomingChatId` is set in the logs
243
+
244
+ ### Authentication errors
245
+ - If `CALLBACK_AUTH_TOKEN` is set, make sure to include it in the request headers
246
+ - Use either `x-callback-token` or `Authorization: Bearer` header
247
+
248
+ ## Environment Variables
249
+
250
+ No additional environment variables are required. The scheduler uses the existing callback server configuration:
251
+
252
+ - `CALLBACK_HOST` - Host for callback server (default: 127.0.0.1)
253
+ - `CALLBACK_PORT` - Port for callback server (default: 8788)
254
+ - `CALLBACK_AUTH_TOKEN` - Optional authentication token
255
+ - `TZ` - Timezone for cron schedules (default: UTC)