cron-claude 1.0.13 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +103 -214
- package/dist/cli.js +82 -10
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +31 -16
- package/dist/config.js +43 -2
- package/dist/config.js.map +1 -1
- package/dist/mcp-server.js +93 -11
- package/dist/mcp-server.js.map +1 -1
- package/package.json +5 -10
- package/dist/daemon.d.ts +0 -13
- package/dist/daemon.js +0 -104
- package/dist/daemon.js.map +0 -1
- package/dist/scheduler.d.ts +0 -20
- package/dist/scheduler.js +0 -143
- package/dist/scheduler.js.map +0 -1
- package/install.sh +0 -59
- package/postinstall.js +0 -13
package/README.md
CHANGED
|
@@ -1,20 +1,22 @@
|
|
|
1
1
|
# cron-claude
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
[](https://www.npmjs.com/package/cron-claude)
|
|
5
|
-
[](https://opensource.org/licenses/MIT)
|
|
3
|
+
> Schedule tasks for Claude. Claude runs them — with full tool access.
|
|
6
4
|
|
|
7
|
-
|
|
5
|
+
## The problem with daemon-based cron
|
|
8
6
|
|
|
9
|
-
|
|
7
|
+
The old approach spawned `claude --print` on a schedule. `--print` disables MCP tools. No Slack, no bash, no files — just text in, text out. You had to use `--dangerously-skip-permissions` just to get anything done.
|
|
10
8
|
|
|
11
|
-
|
|
9
|
+
## How v2 works
|
|
12
10
|
|
|
13
|
-
|
|
11
|
+
**Claude is the daemon.** You paste one line into a Claude Code session and it loops forever:
|
|
14
12
|
|
|
15
|
-
|
|
13
|
+
1. Every 60s: call `get_due_jobs` → atomically claims due jobs (disk state = source of truth)
|
|
14
|
+
2. For each due job: spawn a **subagent** with the job's prompt
|
|
15
|
+
3. Subagent does the work with full tool access (Slack, bash, files, any MCP)
|
|
16
|
+
4. Subagent calls `mark_job_run` → releases the lock, writes a log
|
|
17
|
+
5. Subagents run in parallel — no blocking
|
|
16
18
|
|
|
17
|
-
|
|
19
|
+
No background daemon. No LaunchAgent. No permission dialogs. Survives Claude session restarts (disk state persists).
|
|
18
20
|
|
|
19
21
|
---
|
|
20
22
|
|
|
@@ -24,144 +26,125 @@ Use `cron-claude` when you want scheduled Claude automation without the full Ope
|
|
|
24
26
|
npm install -g cron-claude
|
|
25
27
|
```
|
|
26
28
|
|
|
27
|
-
On macOS, the LaunchAgent is automatically installed so the daemon starts on login. On other platforms, start the daemon manually with `cron-claude-daemon` or use your system's process manager.
|
|
28
|
-
|
|
29
|
-
---
|
|
30
|
-
|
|
31
29
|
## Quick Start
|
|
32
30
|
|
|
31
|
+
**1. Install the MCP server into Claude Code:**
|
|
33
32
|
```bash
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
cron-claude mcp install
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
**2. Add a job:**
|
|
37
|
+
```bash
|
|
38
|
+
cron-claude add \
|
|
39
|
+
--id morning-standup \
|
|
40
|
+
--schedule "0 9 * * 1-5" \
|
|
41
|
+
--prompt "Post a morning standup summary to the #standup Slack channel. Include what's in my calendar today."
|
|
42
|
+
```
|
|
36
43
|
|
|
37
|
-
|
|
38
|
-
cron-claude list
|
|
44
|
+
**3. Start the loop in Claude Code:**
|
|
39
45
|
|
|
40
|
-
|
|
41
|
-
|
|
46
|
+
Paste this into any Claude Code session (or use the `cron-loop` prompt from the MCP prompt picker):
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
Call start_loop to begin.
|
|
42
50
|
```
|
|
43
51
|
|
|
44
|
-
|
|
52
|
+
That's it. Claude will read its operating instructions from `start_loop` and begin polling every 60 seconds.
|
|
45
53
|
|
|
46
54
|
---
|
|
47
55
|
|
|
48
|
-
## CLI
|
|
56
|
+
## CLI Commands
|
|
57
|
+
|
|
58
|
+
| Command | Description |
|
|
59
|
+
|---------|-------------|
|
|
60
|
+
| `cron-claude list` | List all jobs with status, last run, schedule |
|
|
61
|
+
| `cron-claude add --id <id> --schedule <cron> --prompt <text>` | Add a new job |
|
|
62
|
+
| `cron-claude remove <id>` | Remove a job |
|
|
63
|
+
| `cron-claude enable <id>` | Enable a job |
|
|
64
|
+
| `cron-claude disable <id>` | Disable a job |
|
|
65
|
+
| `cron-claude status` | Summary of job counts |
|
|
66
|
+
| `cron-claude agent-loop` | Print setup instructions |
|
|
67
|
+
| `cron-claude mcp install` | Install MCP into Claude Code |
|
|
68
|
+
| `cron-claude stop` | Stop and remove the legacy v1 LaunchAgent daemon |
|
|
69
|
+
|
|
70
|
+
### `add` options
|
|
71
|
+
|
|
72
|
+
| Flag | Default | Description |
|
|
73
|
+
|------|---------|-------------|
|
|
74
|
+
| `--id` | required | Unique job identifier |
|
|
75
|
+
| `--schedule` | required | Cron expression (e.g. `"0 9 * * 1-5"`) |
|
|
76
|
+
| `--prompt` | required | What to tell Claude to do |
|
|
77
|
+
| `--model` | `sonnet` | Claude model for the subagent |
|
|
78
|
+
| `--disabled` | — | Create the job in disabled state |
|
|
49
79
|
|
|
50
|
-
|
|
51
|
-
List all scheduled jobs.
|
|
80
|
+
---
|
|
52
81
|
|
|
53
|
-
|
|
54
|
-
ID Schedule Model Enabled Prompt
|
|
55
|
-
--------------------------------------------------------------------------------
|
|
56
|
-
daily-summary 0 14 * * * sonnet true Summarize my day...
|
|
57
|
-
weekly-review 0 9 * * 1 opus true Weekly project review
|
|
58
|
-
```
|
|
82
|
+
## MCP Tools
|
|
59
83
|
|
|
60
|
-
|
|
61
|
-
Add a new scheduled job.
|
|
84
|
+
The `cron-claude-mcp` server exposes these tools to Claude:
|
|
62
85
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
86
|
+
| Tool | Description |
|
|
87
|
+
|------|-------------|
|
|
88
|
+
| `start_loop` | Call once to get operating instructions (entry point) |
|
|
89
|
+
| `get_due_jobs` | Returns due jobs, atomically marks them `running` |
|
|
90
|
+
| `mark_job_run` | Clears running state, writes log. Call after each job. |
|
|
91
|
+
| `add_cron` | Add a new job |
|
|
92
|
+
| `list_crons` | List all jobs |
|
|
93
|
+
| `remove_cron` | Remove a job by ID |
|
|
94
|
+
| `enable_cron` | Enable a job |
|
|
95
|
+
| `disable_cron` | Disable a job |
|
|
96
|
+
| `get_status` | Get job counts (total, enabled, disabled, running) |
|
|
71
97
|
|
|
72
|
-
|
|
73
|
-
| Flag | Required | Default | Description |
|
|
74
|
-
|------|----------|---------|-------------|
|
|
75
|
-
| `--id` | ✅ | — | Unique job identifier |
|
|
76
|
-
| `--schedule` | ✅ | — | Cron expression |
|
|
77
|
-
| `--prompt` | ✅ | — | Prompt to send Claude |
|
|
78
|
-
| `--model` | ❌ | `sonnet` | Claude model (`sonnet`, `opus`, `haiku`) |
|
|
79
|
-
| `--disabled` | ❌ | — | Create job in disabled state |
|
|
98
|
+
### MCP Prompts
|
|
80
99
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
cron-claude add --id daily-summary --schedule "0 14 * * *" --prompt "Summarize my day"
|
|
85
|
-
|
|
86
|
-
# Weekly Monday 9 AM with opus
|
|
87
|
-
cron-claude add --id weekly-review --schedule "0 9 * * 1" --prompt "Weekly project review" --model opus
|
|
100
|
+
| Prompt | Description |
|
|
101
|
+
|--------|-------------|
|
|
102
|
+
| `cron-loop` | Tells Claude to call `start_loop` — use from the prompt picker |
|
|
88
103
|
|
|
89
|
-
|
|
90
|
-
cron-claude add --id heartbeat --schedule "*/30 * * * *" --prompt "Check system health" --disabled
|
|
91
|
-
```
|
|
104
|
+
---
|
|
92
105
|
|
|
93
|
-
|
|
94
|
-
Remove a job permanently.
|
|
106
|
+
## Atomic Job Locking
|
|
95
107
|
|
|
96
|
-
|
|
97
|
-
cron-claude remove daily-summary
|
|
98
|
-
```
|
|
108
|
+
`get_due_jobs` atomically claims jobs before returning them:
|
|
99
109
|
|
|
100
|
-
|
|
101
|
-
|
|
110
|
+
1. Finds jobs where: `enabled=true`, `status=idle`, `lastRunAt` was >55s ago, cron schedule fired in last 60s
|
|
111
|
+
2. Sets `status=running`, `startedAt=now` on disk **before** returning the list
|
|
112
|
+
3. A second call to `get_due_jobs` sees `status=running` and skips those jobs
|
|
102
113
|
|
|
103
|
-
|
|
104
|
-
cron-claude disable weekly-review
|
|
105
|
-
cron-claude enable weekly-review
|
|
106
|
-
```
|
|
114
|
+
This prevents duplicate execution if two loop iterations somehow overlap.
|
|
107
115
|
|
|
108
|
-
|
|
109
|
-
Show a summary of all jobs.
|
|
116
|
+
`mark_job_run` resets `status=idle`, records `lastRunAt`, and writes a log to `~/.cron-claude/logs/`.
|
|
110
117
|
|
|
118
|
+
If a job is stuck `running` for >10 minutes (subagent crashed), call:
|
|
111
119
|
```
|
|
112
|
-
|
|
113
|
-
Total jobs: 3
|
|
114
|
-
Enabled: 2
|
|
115
|
-
Disabled: 1
|
|
120
|
+
mark_job_run with id="<job-id>", error="timeout"
|
|
116
121
|
```
|
|
117
122
|
|
|
118
|
-
### `cron-claude --version`
|
|
119
|
-
Show the installed version.
|
|
120
|
-
|
|
121
123
|
---
|
|
122
124
|
|
|
123
|
-
##
|
|
124
|
-
|
|
125
|
-
`cron-claude` ships with an MCP server (`cron-claude-mcp`) that lets you manage your cron jobs from directly inside Claude Code or any MCP-compatible client.
|
|
125
|
+
## Logs
|
|
126
126
|
|
|
127
|
-
|
|
127
|
+
Logs are written to `~/.cron-claude/logs/` as `<job-id>_<timestamp>.log`:
|
|
128
128
|
|
|
129
|
-
```json
|
|
130
|
-
{
|
|
131
|
-
"mcpServers": {
|
|
132
|
-
"cron-claude": {
|
|
133
|
-
"command": "cron-claude-mcp"
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
129
|
```
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
| Tool | Description | Parameters |
|
|
142
|
-
|------|-------------|------------|
|
|
143
|
-
| `add_cron` | Add a new scheduled job | `id`, `schedule`, `prompt`, `model?`, `disabled?` |
|
|
144
|
-
| `list_crons` | List all jobs | — |
|
|
145
|
-
| `remove_cron` | Remove a job | `id` |
|
|
146
|
-
| `enable_cron` | Enable a job | `id` |
|
|
147
|
-
| `disable_cron` | Disable a job | `id` |
|
|
148
|
-
| `get_status` | Get job counts (total/enabled/disabled) | — |
|
|
149
|
-
|
|
130
|
+
Job: morning-standup
|
|
131
|
+
Time: 2025-01-15T09:00:03.241Z
|
|
132
|
+
Status: success
|
|
150
133
|
---
|
|
134
|
+
Posted standup to #standup. Calendar shows: 10am design review, 2pm 1:1 with Alex.
|
|
135
|
+
```
|
|
151
136
|
|
|
152
|
-
|
|
137
|
+
---
|
|
153
138
|
|
|
154
|
-
|
|
139
|
+
## Why Not `--print` Mode?
|
|
155
140
|
|
|
156
|
-
|
|
157
|
-
claude plugin marketplace add github:tygiacalone/cron-claude
|
|
158
|
-
```
|
|
141
|
+
`claude --print` disables all MCP tools. You can't use Slack MCP, bash, file access, or any external integrations. The only way around it was `--dangerously-skip-permissions`, which bypasses all permission checks.
|
|
159
142
|
|
|
160
|
-
|
|
143
|
+
In agent loop mode, subagents run inside your existing Claude session with all your approved MCP servers already connected. No flags needed.
|
|
161
144
|
|
|
162
145
|
---
|
|
163
146
|
|
|
164
|
-
##
|
|
147
|
+
## Configuration
|
|
165
148
|
|
|
166
149
|
Jobs are stored in `~/.cron-claude/jobs.json`:
|
|
167
150
|
|
|
@@ -169,127 +152,33 @@ Jobs are stored in `~/.cron-claude/jobs.json`:
|
|
|
169
152
|
{
|
|
170
153
|
"jobs": [
|
|
171
154
|
{
|
|
172
|
-
"id": "
|
|
173
|
-
"schedule": "0
|
|
174
|
-
"prompt": "
|
|
155
|
+
"id": "morning-standup",
|
|
156
|
+
"schedule": "0 9 * * 1-5",
|
|
157
|
+
"prompt": "Post a morning standup to #standup",
|
|
175
158
|
"model": "sonnet",
|
|
176
|
-
"enabled": true
|
|
159
|
+
"enabled": true,
|
|
160
|
+
"status": "idle",
|
|
161
|
+
"lastRunAt": 1736931603241,
|
|
162
|
+
"startedAt": null
|
|
177
163
|
}
|
|
178
164
|
]
|
|
179
165
|
}
|
|
180
166
|
```
|
|
181
167
|
|
|
182
|
-
You can edit this file directly — the daemon watches for changes and reloads automatically.
|
|
183
|
-
|
|
184
|
-
### Cron Syntax
|
|
185
|
-
|
|
186
|
-
Standard 5-field cron: `minute hour day-of-month month day-of-week`
|
|
187
|
-
|
|
188
|
-
| Expression | Meaning |
|
|
189
|
-
|------------|---------|
|
|
190
|
-
| `0 14 * * *` | Every day at 2:00 PM |
|
|
191
|
-
| `*/30 * * * *` | Every 30 minutes |
|
|
192
|
-
| `0 9 * * 1` | Every Monday at 9:00 AM |
|
|
193
|
-
| `0 0 1 * *` | First of each month at midnight |
|
|
194
|
-
| `0 8-18 * * 1-5` | Every hour, 8 AM–6 PM, weekdays |
|
|
195
|
-
|
|
196
|
-
---
|
|
197
|
-
|
|
198
|
-
## Logs
|
|
199
|
-
|
|
200
|
-
Job output is saved to `~/.cron-claude/logs/` with timestamped filenames:
|
|
201
|
-
|
|
202
|
-
```
|
|
203
|
-
~/.cron-claude/logs/
|
|
204
|
-
daily-summary_2026-02-19T14-00-00-000Z.log
|
|
205
|
-
weekly-review_2026-02-17T09-00-00-000Z.log
|
|
206
|
-
```
|
|
207
|
-
|
|
208
|
-
Each log includes the job ID, timestamp, schedule, model, status, and Claude's output.
|
|
209
|
-
|
|
210
168
|
---
|
|
211
169
|
|
|
212
|
-
##
|
|
213
|
-
|
|
214
|
-
```
|
|
215
|
-
┌─────────────────────────────────────────────────┐
|
|
216
|
-
│ cron-claude daemon │
|
|
217
|
-
│ │
|
|
218
|
-
│ ┌─────────────┐ ┌──────────────────────┐ │
|
|
219
|
-
│ │ Scheduler │───▶│ claude --print ... │ │
|
|
220
|
-
│ │ (node-cron) │ │ (Claude CLI exec) │ │
|
|
221
|
-
│ └─────────────┘ └──────────────────────┘ │
|
|
222
|
-
│ ▲ │ │
|
|
223
|
-
│ │ ▼ │
|
|
224
|
-
│ ┌─────────────┐ ┌──────────────────────┐ │
|
|
225
|
-
│ │ jobs.json │ │ ~/.cron-claude/logs/ │ │
|
|
226
|
-
│ │ (config) │ │ (output logs) │ │
|
|
227
|
-
│ └─────────────┘ └──────────────────────┘ │
|
|
228
|
-
└─────────────────────────────────────────────────┘
|
|
229
|
-
▲
|
|
230
|
-
│ reads/writes
|
|
231
|
-
┌─────────────┐ ┌─────────────┐
|
|
232
|
-
│ cron-claude │ │ cron-claude │
|
|
233
|
-
│ (CLI) │ │ -mcp (MCP) │
|
|
234
|
-
└─────────────┘ └─────────────┘
|
|
235
|
-
```
|
|
236
|
-
|
|
237
|
-
**Components:**
|
|
238
|
-
- **Daemon** (`src/daemon.ts`): Loads jobs from config, schedules them via `node-cron`, watches for file changes
|
|
239
|
-
- **Scheduler** (`src/scheduler.ts`): Wraps `node-cron`, executes jobs via `execFile(claude, ...)`, logs output
|
|
240
|
-
- **Config** (`src/config.ts`): Reads/writes `~/.cron-claude/jobs.json`, validates with Zod
|
|
241
|
-
- **CLI** (`src/cli.ts`): Commander-based CLI for managing jobs
|
|
242
|
-
- **MCP Server** (`src/mcp-server.ts`): Exposes all job management as MCP tools
|
|
243
|
-
|
|
244
|
-
---
|
|
170
|
+
## Upgrading from v1
|
|
245
171
|
|
|
246
|
-
|
|
172
|
+
If you ran v1 (daemon mode), stop the LaunchAgent:
|
|
247
173
|
|
|
248
174
|
```bash
|
|
249
|
-
|
|
250
|
-
cd cron-claude
|
|
251
|
-
npm install
|
|
252
|
-
|
|
253
|
-
# Build
|
|
254
|
-
npm run build
|
|
255
|
-
|
|
256
|
-
# Run tests with coverage
|
|
257
|
-
npm test
|
|
258
|
-
|
|
259
|
-
# Run CLI in dev mode (tsx, no build needed)
|
|
260
|
-
npm run cli -- list
|
|
261
|
-
npm run cli -- add --id test --schedule "* * * * *" --prompt "hello"
|
|
262
|
-
|
|
263
|
-
# Run daemon in dev mode
|
|
264
|
-
npm run dev
|
|
175
|
+
cron-claude stop
|
|
265
176
|
```
|
|
266
177
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
```
|
|
270
|
-
src/
|
|
271
|
-
cli.ts # Commander CLI
|
|
272
|
-
config.ts # Config read/write with Zod validation
|
|
273
|
-
daemon.ts # Main daemon (loads config, watches for changes)
|
|
274
|
-
scheduler.ts # node-cron wrapper + Claude CLI executor
|
|
275
|
-
mcp-server.ts # MCP server (StdioServerTransport)
|
|
276
|
-
plugin/ # Claude Code plugin descriptor
|
|
277
|
-
tests/
|
|
278
|
-
cli.test.ts
|
|
279
|
-
config.test.ts
|
|
280
|
-
daemon.test.ts
|
|
281
|
-
scheduler.test.ts
|
|
282
|
-
mcp-server.test.ts
|
|
283
|
-
.github/workflows/ci.yml
|
|
284
|
-
.claude-plugin/
|
|
285
|
-
marketplace.json
|
|
286
|
-
plugin.json
|
|
287
|
-
install.sh # macOS LaunchAgent installer
|
|
288
|
-
postinstall.js # npm postinstall hook (auto-runs install.sh on macOS global install)
|
|
289
|
-
```
|
|
178
|
+
Your jobs in `~/.cron-claude/jobs.json` are migrated automatically — v2 just ignores the old `headless`, `dangerouslySkipPermissions`, and `executor` fields (they'll be stripped on next write).
|
|
290
179
|
|
|
291
180
|
---
|
|
292
181
|
|
|
293
182
|
## License
|
|
294
183
|
|
|
295
|
-
MIT
|
|
184
|
+
MIT
|
package/dist/cli.js
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { Command } from 'commander';
|
|
3
3
|
import { createRequire } from 'module';
|
|
4
|
-
import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'fs';
|
|
4
|
+
import { readFileSync, writeFileSync, mkdirSync, existsSync, rmSync } from 'fs';
|
|
5
5
|
import { join } from 'path';
|
|
6
6
|
import { homedir } from 'os';
|
|
7
|
+
import { execSync } from 'child_process';
|
|
7
8
|
import { addJob, removeJob, listJobs, toggleJob, JobSchema } from './config.js';
|
|
8
9
|
const require = createRequire(import.meta.url);
|
|
9
10
|
const { version } = require('../package.json');
|
|
10
11
|
const program = new Command();
|
|
11
12
|
program
|
|
12
13
|
.name('cron-claude')
|
|
13
|
-
.description('Manage scheduled Claude
|
|
14
|
+
.description('Manage scheduled Claude jobs (agent loop mode)')
|
|
14
15
|
.version(version);
|
|
15
16
|
program
|
|
16
17
|
.command('list')
|
|
@@ -21,10 +22,18 @@ program
|
|
|
21
22
|
console.log('No jobs configured.');
|
|
22
23
|
return;
|
|
23
24
|
}
|
|
24
|
-
console.log(`\n${'ID'.padEnd(20)} ${'Schedule'.padEnd(15)} ${'Model'.padEnd(10)} ${'Enabled'.padEnd(8)} ${'
|
|
25
|
-
console.log('-'.repeat(
|
|
25
|
+
console.log(`\n${'ID'.padEnd(20)} ${'Schedule'.padEnd(15)} ${'Model'.padEnd(10)} ${'Enabled'.padEnd(8)} ${'Status'.padEnd(18)} ${'Last Run'.padEnd(22)} Prompt`);
|
|
26
|
+
console.log('-'.repeat(115));
|
|
26
27
|
for (const job of jobs) {
|
|
27
|
-
|
|
28
|
+
const lastRun = job.lastRunAt
|
|
29
|
+
? new Date(job.lastRunAt).toLocaleString()
|
|
30
|
+
: 'never';
|
|
31
|
+
let statusStr = job.status ?? 'idle';
|
|
32
|
+
if (job.status === 'running' && job.startedAt) {
|
|
33
|
+
const mins = Math.floor((Date.now() - job.startedAt) / 60000);
|
|
34
|
+
statusStr = `running (${mins}min ago)`;
|
|
35
|
+
}
|
|
36
|
+
console.log(`${job.id.padEnd(20)} ${job.schedule.padEnd(15)} ${job.model.padEnd(10)} ${String(job.enabled).padEnd(8)} ${statusStr.padEnd(18)} ${lastRun.padEnd(22)} ${job.prompt.slice(0, 40)}`);
|
|
28
37
|
}
|
|
29
38
|
console.log('');
|
|
30
39
|
});
|
|
@@ -36,8 +45,6 @@ program
|
|
|
36
45
|
.requiredOption('--prompt <prompt>', 'Prompt to send to Claude')
|
|
37
46
|
.option('--model <model>', 'Claude model to use', 'sonnet')
|
|
38
47
|
.option('--disabled', 'Create job in disabled state')
|
|
39
|
-
.option('--no-headless', 'Run as full agent (tool use, bash, files) instead of --print mode')
|
|
40
|
-
.option('--dangerously-skip-permissions', 'Pass --dangerously-skip-permissions to claude (skips all permission prompts)')
|
|
41
48
|
.action((opts) => {
|
|
42
49
|
try {
|
|
43
50
|
const job = JobSchema.parse({
|
|
@@ -46,8 +53,6 @@ program
|
|
|
46
53
|
prompt: opts.prompt,
|
|
47
54
|
model: opts.model,
|
|
48
55
|
enabled: !opts.disabled,
|
|
49
|
-
headless: opts.headless,
|
|
50
|
-
dangerouslySkipPermissions: opts.dangerouslySkipPermissions ?? false,
|
|
51
56
|
});
|
|
52
57
|
addJob(job);
|
|
53
58
|
console.log(`Job "${job.id}" added successfully.`);
|
|
@@ -98,7 +103,7 @@ program
|
|
|
98
103
|
});
|
|
99
104
|
program
|
|
100
105
|
.command('status')
|
|
101
|
-
.description('Show
|
|
106
|
+
.description('Show job status summary')
|
|
102
107
|
.action(() => {
|
|
103
108
|
const jobs = listJobs();
|
|
104
109
|
const enabled = jobs.filter((j) => j.enabled).length;
|
|
@@ -108,6 +113,73 @@ program
|
|
|
108
113
|
console.log(` Enabled: ${enabled}`);
|
|
109
114
|
console.log(` Disabled: ${disabled}\n`);
|
|
110
115
|
});
|
|
116
|
+
program
|
|
117
|
+
.command('stop')
|
|
118
|
+
.description('Stop and remove the legacy cron-claude LaunchAgent daemon (if running)')
|
|
119
|
+
.action(() => {
|
|
120
|
+
const plistPath = join(homedir(), 'Library', 'LaunchAgents', 'com.cron-claude.daemon.plist');
|
|
121
|
+
try {
|
|
122
|
+
execSync(`launchctl unload "${plistPath}" 2>/dev/null || true`, { stdio: 'ignore' });
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
// ignore launchctl errors
|
|
126
|
+
}
|
|
127
|
+
if (existsSync(plistPath)) {
|
|
128
|
+
rmSync(plistPath);
|
|
129
|
+
}
|
|
130
|
+
console.log('Daemon stopped and removed.');
|
|
131
|
+
});
|
|
132
|
+
program
|
|
133
|
+
.command('agent-loop')
|
|
134
|
+
.description('Show instructions for running cron-claude in Claude agent loop mode')
|
|
135
|
+
.action(() => {
|
|
136
|
+
const jobs = listJobs();
|
|
137
|
+
console.log(`
|
|
138
|
+
Agent Loop Mode
|
|
139
|
+
===============
|
|
140
|
+
cron-claude v2 uses Claude itself as the cron executor — no background daemon needed.
|
|
141
|
+
|
|
142
|
+
QUICKSTART
|
|
143
|
+
----------
|
|
144
|
+
1. Install the MCP (once):
|
|
145
|
+
cron-claude mcp install
|
|
146
|
+
|
|
147
|
+
2. Paste this into a Claude Code session:
|
|
148
|
+
|
|
149
|
+
"Call start_loop to begin."
|
|
150
|
+
|
|
151
|
+
(Or use the built-in 'cron-loop' MCP prompt from the prompt picker)
|
|
152
|
+
|
|
153
|
+
3. Claude will call start_loop, receive operating instructions, then loop forever:
|
|
154
|
+
• Every 60s: call get_due_jobs (atomically claims due jobs)
|
|
155
|
+
• For each due job: spawn a SUBAGENT with the job prompt
|
|
156
|
+
• Subagent calls mark_job_run when done (releases the lock + writes log)
|
|
157
|
+
• Subagents run IN PARALLEL — no blocking
|
|
158
|
+
|
|
159
|
+
WHY SUBAGENTS?
|
|
160
|
+
--------------
|
|
161
|
+
Subagents get full tool access: Slack MCP, bash, files, APIs — everything.
|
|
162
|
+
No --print flag, no --dangerously-skip-permissions, no permission dialogs.
|
|
163
|
+
The disk is the source of truth. Survives Claude session restarts.
|
|
164
|
+
|
|
165
|
+
LOGS
|
|
166
|
+
----
|
|
167
|
+
~/.cron-claude/logs/
|
|
168
|
+
|
|
169
|
+
YOUR JOBS`);
|
|
170
|
+
if (jobs.length === 0) {
|
|
171
|
+
console.log(' (none — use "cron-claude add" to add one)');
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
for (const job of jobs) {
|
|
175
|
+
const lastRun = job.lastRunAt ? new Date(job.lastRunAt).toLocaleString() : 'never';
|
|
176
|
+
const statusStr = job.status === 'running' ? ' [RUNNING]' : '';
|
|
177
|
+
console.log(` [${job.enabled ? 'ON ' : 'OFF'}] ${job.id}${statusStr} | ${job.schedule} | last: ${lastRun}`);
|
|
178
|
+
console.log(` ${job.prompt.slice(0, 80)}`);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
console.log('');
|
|
182
|
+
});
|
|
111
183
|
const mcpCmd = program
|
|
112
184
|
.command('mcp')
|
|
113
185
|
.description('MCP server management');
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|