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/.env.example +48 -0
- package/LICENSE +21 -0
- package/QUICKSTART-SCHEDULER.md +226 -0
- package/QUICKSTART.md +98 -0
- package/README.md +404 -0
- package/SCHEDULER.md +255 -0
- package/TESTING.md +239 -0
- package/acp/clientHelpers.ts +23 -0
- package/acp/tempAcpRunner.ts +320 -0
- package/agent-bridge.config.example.json +19 -0
- package/bin/cli.ts +255 -0
- package/dist/acp/clientHelpers.js +19 -0
- package/dist/acp/tempAcpRunner.js +263 -0
- package/dist/bin/cli.js +217 -0
- package/dist/index.js +1115 -0
- package/dist/messaging/telegramClient.js +109 -0
- package/dist/scheduler/cronScheduler.js +272 -0
- package/dist/scheduler/scheduledJobHandler.js +34 -0
- package/dist/utils/error.js +12 -0
- package/dist/utils/telegramMarkdown.js +128 -0
- package/ecosystem.config.json +23 -0
- package/index.ts +1272 -0
- package/messaging/telegramClient.ts +132 -0
- package/package.json +43 -0
- package/scheduler/cronScheduler.ts +355 -0
- package/scheduler/scheduledJobHandler.ts +55 -0
- package/scripts/callback-health.sh +6 -0
- package/scripts/callback-post-chat.sh +25 -0
- package/scripts/callback-post.sh +19 -0
- package/scripts/gemini-scheduler-examples.sh +162 -0
- package/scripts/test-scheduler.sh +78 -0
- package/tsconfig.json +23 -0
- package/utils/error.ts +12 -0
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)
|