@patrick-rodgers/cron-claude 0.1.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.
- package/LICENSE +21 -0
- package/README.md +401 -0
- package/dist/cli.d.ts +7 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +296 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +22 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +61 -0
- package/dist/config.js.map +1 -0
- package/dist/executor.d.ts +19 -0
- package/dist/executor.d.ts.map +1 -0
- package/dist/executor.js +234 -0
- package/dist/executor.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +27 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +42 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +178 -0
- package/dist/logger.js.map +1 -0
- package/dist/mcp-server.d.ts +7 -0
- package/dist/mcp-server.d.ts.map +1 -0
- package/dist/mcp-server.js +580 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/notifier.d.ts +17 -0
- package/dist/notifier.d.ts.map +1 -0
- package/dist/notifier.js +48 -0
- package/dist/notifier.js.map +1 -0
- package/dist/scheduler.d.ts +46 -0
- package/dist/scheduler.d.ts.map +1 -0
- package/dist/scheduler.js +230 -0
- package/dist/scheduler.js.map +1 -0
- package/dist/types.d.ts +37 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/install.ps1 +93 -0
- package/package.json +52 -0
- package/uninstall.ps1 +59 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Windows Task Scheduler integration
|
|
3
|
+
* Converts cron expressions to Task Scheduler triggers and manages scheduled tasks
|
|
4
|
+
*/
|
|
5
|
+
interface ScheduleTrigger {
|
|
6
|
+
type: 'daily' | 'weekly' | 'monthly' | 'once' | 'startup';
|
|
7
|
+
time?: string;
|
|
8
|
+
days?: string[];
|
|
9
|
+
interval?: number;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Parse cron expression and convert to Task Scheduler trigger
|
|
13
|
+
* Cron format: minute hour day month weekday
|
|
14
|
+
*/
|
|
15
|
+
export declare function parseCronExpression(cronExpr: string): ScheduleTrigger;
|
|
16
|
+
/**
|
|
17
|
+
* Generate PowerShell command to create scheduled task
|
|
18
|
+
*/
|
|
19
|
+
export declare function generateTaskSchedulerCommand(taskId: string, taskFilePath: string, trigger: ScheduleTrigger, projectRoot: string): string;
|
|
20
|
+
/**
|
|
21
|
+
* Register a task in Windows Task Scheduler
|
|
22
|
+
*/
|
|
23
|
+
export declare function registerTask(taskId: string, taskFilePath: string, cronExpr: string, projectRoot: string): void;
|
|
24
|
+
/**
|
|
25
|
+
* Unregister a task from Windows Task Scheduler
|
|
26
|
+
*/
|
|
27
|
+
export declare function unregisterTask(taskId: string): void;
|
|
28
|
+
/**
|
|
29
|
+
* Enable a task in Windows Task Scheduler
|
|
30
|
+
*/
|
|
31
|
+
export declare function enableTask(taskId: string): void;
|
|
32
|
+
/**
|
|
33
|
+
* Disable a task in Windows Task Scheduler
|
|
34
|
+
*/
|
|
35
|
+
export declare function disableTask(taskId: string): void;
|
|
36
|
+
/**
|
|
37
|
+
* Get task status from Windows Task Scheduler
|
|
38
|
+
*/
|
|
39
|
+
export declare function getTaskStatus(taskId: string): {
|
|
40
|
+
exists: boolean;
|
|
41
|
+
enabled?: boolean;
|
|
42
|
+
lastRunTime?: string;
|
|
43
|
+
nextRunTime?: string;
|
|
44
|
+
};
|
|
45
|
+
export {};
|
|
46
|
+
//# sourceMappingURL=scheduler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scheduler.d.ts","sourceRoot":"","sources":["../src/scheduler.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,UAAU,eAAe;IACvB,IAAI,EAAE,OAAO,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAAC;IAC1D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,eAAe,CA+CrE;AAED;;GAEG;AACH,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,eAAe,EACxB,WAAW,EAAE,MAAM,GAClB,MAAM,CA8DR;AAED;;GAEG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,GAClB,IAAI,CAqBN;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAenD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAe/C;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAehD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG;IAC7C,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAsBA"}
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Windows Task Scheduler integration
|
|
4
|
+
* Converts cron expressions to Task Scheduler triggers and manages scheduled tasks
|
|
5
|
+
*/
|
|
6
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
7
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
8
|
+
};
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.parseCronExpression = parseCronExpression;
|
|
11
|
+
exports.generateTaskSchedulerCommand = generateTaskSchedulerCommand;
|
|
12
|
+
exports.registerTask = registerTask;
|
|
13
|
+
exports.unregisterTask = unregisterTask;
|
|
14
|
+
exports.enableTask = enableTask;
|
|
15
|
+
exports.disableTask = disableTask;
|
|
16
|
+
exports.getTaskStatus = getTaskStatus;
|
|
17
|
+
const child_process_1 = require("child_process");
|
|
18
|
+
const path_1 = require("path");
|
|
19
|
+
const node_cron_1 = __importDefault(require("node-cron"));
|
|
20
|
+
/**
|
|
21
|
+
* Parse cron expression and convert to Task Scheduler trigger
|
|
22
|
+
* Cron format: minute hour day month weekday
|
|
23
|
+
*/
|
|
24
|
+
function parseCronExpression(cronExpr) {
|
|
25
|
+
// Validate cron expression first
|
|
26
|
+
if (!node_cron_1.default.validate(cronExpr)) {
|
|
27
|
+
throw new Error(`Invalid cron expression: ${cronExpr}`);
|
|
28
|
+
}
|
|
29
|
+
const parts = cronExpr.split(' ');
|
|
30
|
+
if (parts.length !== 5) {
|
|
31
|
+
throw new Error(`Invalid cron expression format: ${cronExpr}`);
|
|
32
|
+
}
|
|
33
|
+
const [minute, hour, dayOfMonth, month, dayOfWeek] = parts;
|
|
34
|
+
// Determine trigger type and details
|
|
35
|
+
const trigger = { type: 'daily' };
|
|
36
|
+
// If hour and minute are specified
|
|
37
|
+
if (hour !== '*' && minute !== '*') {
|
|
38
|
+
const hourNum = parseInt(hour);
|
|
39
|
+
const minuteNum = parseInt(minute);
|
|
40
|
+
trigger.time = `${hourNum.toString().padStart(2, '0')}:${minuteNum.toString().padStart(2, '0')}`;
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
// Default to midnight
|
|
44
|
+
trigger.time = '00:00';
|
|
45
|
+
}
|
|
46
|
+
// Check if it's a weekly schedule (specific day of week)
|
|
47
|
+
if (dayOfWeek !== '*') {
|
|
48
|
+
trigger.type = 'weekly';
|
|
49
|
+
const dayMap = {
|
|
50
|
+
'0': 'SUN',
|
|
51
|
+
'1': 'MON',
|
|
52
|
+
'2': 'TUE',
|
|
53
|
+
'3': 'WED',
|
|
54
|
+
'4': 'THU',
|
|
55
|
+
'5': 'FRI',
|
|
56
|
+
'6': 'SAT',
|
|
57
|
+
'7': 'SUN',
|
|
58
|
+
};
|
|
59
|
+
trigger.days = dayOfWeek.split(',').map((d) => dayMap[d.trim()] || 'MON');
|
|
60
|
+
}
|
|
61
|
+
// Check if it's a monthly schedule (specific day of month)
|
|
62
|
+
else if (dayOfMonth !== '*') {
|
|
63
|
+
trigger.type = 'monthly';
|
|
64
|
+
}
|
|
65
|
+
return trigger;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Generate PowerShell command to create scheduled task
|
|
69
|
+
*/
|
|
70
|
+
function generateTaskSchedulerCommand(taskId, taskFilePath, trigger, projectRoot) {
|
|
71
|
+
const executorPath = (0, path_1.resolve)(projectRoot, 'dist', 'executor.js');
|
|
72
|
+
const absoluteTaskPath = (0, path_1.resolve)(taskFilePath);
|
|
73
|
+
// Build the action command
|
|
74
|
+
const actionCommand = `node "${executorPath}" "${absoluteTaskPath}"`;
|
|
75
|
+
// Build trigger XML based on type
|
|
76
|
+
let triggerXml = '';
|
|
77
|
+
if (trigger.type === 'daily') {
|
|
78
|
+
triggerXml = `
|
|
79
|
+
<CalendarTrigger>
|
|
80
|
+
<StartBoundary>2026-01-01T${trigger.time}:00</StartBoundary>
|
|
81
|
+
<Enabled>true</Enabled>
|
|
82
|
+
<ScheduleByDay>
|
|
83
|
+
<DaysInterval>1</DaysInterval>
|
|
84
|
+
</ScheduleByDay>
|
|
85
|
+
</CalendarTrigger>`;
|
|
86
|
+
}
|
|
87
|
+
else if (trigger.type === 'weekly' && trigger.days) {
|
|
88
|
+
const daysOfWeek = trigger.days.join('');
|
|
89
|
+
triggerXml = `
|
|
90
|
+
<CalendarTrigger>
|
|
91
|
+
<StartBoundary>2026-01-01T${trigger.time}:00</StartBoundary>
|
|
92
|
+
<Enabled>true</Enabled>
|
|
93
|
+
<ScheduleByWeek>
|
|
94
|
+
<WeeksInterval>1</WeeksInterval>
|
|
95
|
+
<DaysOfWeek>
|
|
96
|
+
${trigger.days.map((day) => `<${day} />`).join('\n ')}
|
|
97
|
+
</DaysOfWeek>
|
|
98
|
+
</ScheduleByWeek>
|
|
99
|
+
</CalendarTrigger>`;
|
|
100
|
+
}
|
|
101
|
+
else if (trigger.type === 'monthly') {
|
|
102
|
+
triggerXml = `
|
|
103
|
+
<CalendarTrigger>
|
|
104
|
+
<StartBoundary>2026-01-01T${trigger.time}:00</StartBoundary>
|
|
105
|
+
<Enabled>true</Enabled>
|
|
106
|
+
<ScheduleByMonth>
|
|
107
|
+
<DaysOfMonth>
|
|
108
|
+
<Day>1</Day>
|
|
109
|
+
</DaysOfMonth>
|
|
110
|
+
<Months>
|
|
111
|
+
<January /><February /><March /><April /><May /><June />
|
|
112
|
+
<July /><August /><September /><October /><November /><December />
|
|
113
|
+
</Months>
|
|
114
|
+
</ScheduleByMonth>
|
|
115
|
+
</CalendarTrigger>`;
|
|
116
|
+
}
|
|
117
|
+
// Generate PowerShell script
|
|
118
|
+
const psScript = `
|
|
119
|
+
$taskName = "CronClaude_${taskId}"
|
|
120
|
+
$action = New-ScheduledTaskAction -Execute "node" -Argument '"${executorPath}" "${absoluteTaskPath}"'
|
|
121
|
+
$trigger = New-ScheduledTaskTrigger -Daily -At "${trigger.time || '00:00'}"
|
|
122
|
+
$settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable
|
|
123
|
+
$principal = New-ScheduledTaskPrincipal -UserId "$env:USERNAME" -LogonType S4U
|
|
124
|
+
|
|
125
|
+
Register-ScheduledTask -TaskName $taskName -Action $action -Trigger $trigger -Settings $settings -Principal $principal -Force
|
|
126
|
+
Write-Host "Task registered: $taskName"
|
|
127
|
+
`.trim();
|
|
128
|
+
return psScript;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Register a task in Windows Task Scheduler
|
|
132
|
+
*/
|
|
133
|
+
function registerTask(taskId, taskFilePath, cronExpr, projectRoot) {
|
|
134
|
+
try {
|
|
135
|
+
console.log(`Registering task: ${taskId}`);
|
|
136
|
+
console.log(`Cron expression: ${cronExpr}`);
|
|
137
|
+
const trigger = parseCronExpression(cronExpr);
|
|
138
|
+
console.log(`Trigger type: ${trigger.type}, time: ${trigger.time}`);
|
|
139
|
+
const psCommand = generateTaskSchedulerCommand(taskId, taskFilePath, trigger, projectRoot);
|
|
140
|
+
// Execute PowerShell command
|
|
141
|
+
(0, child_process_1.execSync)(psCommand, {
|
|
142
|
+
shell: 'powershell.exe',
|
|
143
|
+
stdio: 'inherit',
|
|
144
|
+
});
|
|
145
|
+
console.log(`✓ Task "${taskId}" registered successfully`);
|
|
146
|
+
}
|
|
147
|
+
catch (error) {
|
|
148
|
+
console.error(`Failed to register task "${taskId}":`, error);
|
|
149
|
+
throw error;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Unregister a task from Windows Task Scheduler
|
|
154
|
+
*/
|
|
155
|
+
function unregisterTask(taskId) {
|
|
156
|
+
try {
|
|
157
|
+
const taskName = `CronClaude_${taskId}`;
|
|
158
|
+
const psCommand = `Unregister-ScheduledTask -TaskName "${taskName}" -Confirm:$false`;
|
|
159
|
+
(0, child_process_1.execSync)(psCommand, {
|
|
160
|
+
shell: 'powershell.exe',
|
|
161
|
+
stdio: 'inherit',
|
|
162
|
+
});
|
|
163
|
+
console.log(`✓ Task "${taskId}" unregistered successfully`);
|
|
164
|
+
}
|
|
165
|
+
catch (error) {
|
|
166
|
+
console.error(`Failed to unregister task "${taskId}":`, error);
|
|
167
|
+
throw error;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Enable a task in Windows Task Scheduler
|
|
172
|
+
*/
|
|
173
|
+
function enableTask(taskId) {
|
|
174
|
+
try {
|
|
175
|
+
const taskName = `CronClaude_${taskId}`;
|
|
176
|
+
const psCommand = `Enable-ScheduledTask -TaskName "${taskName}"`;
|
|
177
|
+
(0, child_process_1.execSync)(psCommand, {
|
|
178
|
+
shell: 'powershell.exe',
|
|
179
|
+
stdio: 'inherit',
|
|
180
|
+
});
|
|
181
|
+
console.log(`✓ Task "${taskId}" enabled`);
|
|
182
|
+
}
|
|
183
|
+
catch (error) {
|
|
184
|
+
console.error(`Failed to enable task "${taskId}":`, error);
|
|
185
|
+
throw error;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Disable a task in Windows Task Scheduler
|
|
190
|
+
*/
|
|
191
|
+
function disableTask(taskId) {
|
|
192
|
+
try {
|
|
193
|
+
const taskName = `CronClaude_${taskId}`;
|
|
194
|
+
const psCommand = `Disable-ScheduledTask -TaskName "${taskName}"`;
|
|
195
|
+
(0, child_process_1.execSync)(psCommand, {
|
|
196
|
+
shell: 'powershell.exe',
|
|
197
|
+
stdio: 'inherit',
|
|
198
|
+
});
|
|
199
|
+
console.log(`✓ Task "${taskId}" disabled`);
|
|
200
|
+
}
|
|
201
|
+
catch (error) {
|
|
202
|
+
console.error(`Failed to disable task "${taskId}":`, error);
|
|
203
|
+
throw error;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Get task status from Windows Task Scheduler
|
|
208
|
+
*/
|
|
209
|
+
function getTaskStatus(taskId) {
|
|
210
|
+
try {
|
|
211
|
+
const taskName = `CronClaude_${taskId}`;
|
|
212
|
+
const psCommand = `Get-ScheduledTask -TaskName "${taskName}" | Select-Object State, @{Name="LastRunTime";Expression={(Get-ScheduledTaskInfo -TaskName "${taskName}").LastRunTime}}, @{Name="NextRunTime";Expression={(Get-ScheduledTaskInfo -TaskName "${taskName}").NextRunTime}} | ConvertTo-Json`;
|
|
213
|
+
const output = (0, child_process_1.execSync)(psCommand, {
|
|
214
|
+
shell: 'powershell.exe',
|
|
215
|
+
encoding: 'utf-8',
|
|
216
|
+
stdio: 'pipe',
|
|
217
|
+
});
|
|
218
|
+
const data = JSON.parse(output);
|
|
219
|
+
return {
|
|
220
|
+
exists: true,
|
|
221
|
+
enabled: data.State === 'Ready',
|
|
222
|
+
lastRunTime: data.LastRunTime,
|
|
223
|
+
nextRunTime: data.NextRunTime,
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
catch (error) {
|
|
227
|
+
return { exists: false };
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
//# sourceMappingURL=scheduler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../src/scheduler.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core types for cron-claude system
|
|
3
|
+
*/
|
|
4
|
+
export interface TaskDefinition {
|
|
5
|
+
id: string;
|
|
6
|
+
schedule: string;
|
|
7
|
+
invocation: 'cli' | 'api';
|
|
8
|
+
notifications: {
|
|
9
|
+
toast: boolean;
|
|
10
|
+
};
|
|
11
|
+
enabled: boolean;
|
|
12
|
+
instructions: string;
|
|
13
|
+
}
|
|
14
|
+
export interface TaskLog {
|
|
15
|
+
taskId: string;
|
|
16
|
+
executionId: string;
|
|
17
|
+
timestamp: string;
|
|
18
|
+
status: 'success' | 'failure' | 'running';
|
|
19
|
+
steps: LogStep[];
|
|
20
|
+
signature?: string;
|
|
21
|
+
}
|
|
22
|
+
export interface LogStep {
|
|
23
|
+
timestamp: string;
|
|
24
|
+
action: string;
|
|
25
|
+
output?: string;
|
|
26
|
+
error?: string;
|
|
27
|
+
}
|
|
28
|
+
export interface LoggerConfig {
|
|
29
|
+
secretKey: string;
|
|
30
|
+
}
|
|
31
|
+
export interface ExecutionResult {
|
|
32
|
+
success: boolean;
|
|
33
|
+
output: string;
|
|
34
|
+
error?: string;
|
|
35
|
+
steps: LogStep[];
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,KAAK,GAAG,KAAK,CAAC;IAC1B,aAAa,EAAE;QACb,KAAK,EAAE,OAAO,CAAC;KAChB,CAAC;IACF,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,OAAO;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;IAC1C,KAAK,EAAE,OAAO,EAAE,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,OAAO;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,OAAO,EAAE,CAAC;CAClB"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";AAAA;;GAEG"}
|
package/install.ps1
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
#!/usr/bin/env pwsh
|
|
2
|
+
<#
|
|
3
|
+
.SYNOPSIS
|
|
4
|
+
Install cron-claude MCP server to Claude Code configuration
|
|
5
|
+
|
|
6
|
+
.DESCRIPTION
|
|
7
|
+
This script registers the cron-claude MCP server with Claude Code
|
|
8
|
+
so it's available in all local sessions.
|
|
9
|
+
|
|
10
|
+
.EXAMPLE
|
|
11
|
+
.\install.ps1
|
|
12
|
+
#>
|
|
13
|
+
|
|
14
|
+
$ErrorActionPreference = "Stop"
|
|
15
|
+
|
|
16
|
+
Write-Host "Installing cron-claude MCP server..." -ForegroundColor Cyan
|
|
17
|
+
|
|
18
|
+
# Get the project root directory
|
|
19
|
+
$ProjectRoot = $PSScriptRoot
|
|
20
|
+
$MCPServerPath = Join-Path $ProjectRoot "dist\mcp-server.js"
|
|
21
|
+
|
|
22
|
+
# Check if the MCP server exists
|
|
23
|
+
if (-not (Test-Path $MCPServerPath)) {
|
|
24
|
+
Write-Host "Error: MCP server not found at $MCPServerPath" -ForegroundColor Red
|
|
25
|
+
Write-Host "Please run 'npm run build' first" -ForegroundColor Yellow
|
|
26
|
+
exit 1
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
# Get Claude Code config directory
|
|
30
|
+
$ClaudeConfigDir = Join-Path $env:USERPROFILE ".claude"
|
|
31
|
+
$ClaudeConfigFile = Join-Path $ClaudeConfigDir "config.json"
|
|
32
|
+
|
|
33
|
+
# Ensure config directory exists
|
|
34
|
+
if (-not (Test-Path $ClaudeConfigDir)) {
|
|
35
|
+
Write-Host "Creating Claude config directory: $ClaudeConfigDir" -ForegroundColor Yellow
|
|
36
|
+
New-Item -ItemType Directory -Path $ClaudeConfigDir -Force | Out-Null
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
# Read existing config or create new one
|
|
40
|
+
$config = @{
|
|
41
|
+
mcpServers = @{}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (Test-Path $ClaudeConfigFile) {
|
|
45
|
+
Write-Host "Reading existing Claude config..." -ForegroundColor Gray
|
|
46
|
+
$existingConfig = Get-Content $ClaudeConfigFile -Raw | ConvertFrom-Json
|
|
47
|
+
|
|
48
|
+
# Convert PSCustomObject to hashtable
|
|
49
|
+
$config = @{
|
|
50
|
+
mcpServers = @{}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if ($existingConfig.mcpServers) {
|
|
54
|
+
foreach ($property in $existingConfig.mcpServers.PSObject.Properties) {
|
|
55
|
+
$config.mcpServers[$property.Name] = $property.Value
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
# Add or update cron-claude server configuration
|
|
61
|
+
$config.mcpServers["cron-claude"] = @{
|
|
62
|
+
command = "node"
|
|
63
|
+
args = @($MCPServerPath)
|
|
64
|
+
disabled = $false
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
# Write config back
|
|
68
|
+
Write-Host "Updating Claude config..." -ForegroundColor Gray
|
|
69
|
+
$config | ConvertTo-Json -Depth 10 | Set-Content $ClaudeConfigFile -Encoding UTF8
|
|
70
|
+
|
|
71
|
+
Write-Host ""
|
|
72
|
+
Write-Host "✓ Successfully installed cron-claude MCP server!" -ForegroundColor Green
|
|
73
|
+
Write-Host ""
|
|
74
|
+
Write-Host "Configuration saved to: $ClaudeConfigFile" -ForegroundColor Gray
|
|
75
|
+
Write-Host ""
|
|
76
|
+
Write-Host "Available MCP tools:" -ForegroundColor Cyan
|
|
77
|
+
Write-Host " - cron_create_task Create new scheduled tasks"
|
|
78
|
+
Write-Host " - cron_register_task Register with Task Scheduler"
|
|
79
|
+
Write-Host " - cron_list_tasks View all tasks"
|
|
80
|
+
Write-Host " - cron_run_task Execute task immediately"
|
|
81
|
+
Write-Host " - cron_enable_task Enable a task"
|
|
82
|
+
Write-Host " - cron_disable_task Disable a task"
|
|
83
|
+
Write-Host " - cron_unregister_task Remove from scheduler"
|
|
84
|
+
Write-Host " - cron_view_logs View execution history"
|
|
85
|
+
Write-Host " - cron_verify_log Verify log signatures"
|
|
86
|
+
Write-Host " - cron_status System information"
|
|
87
|
+
Write-Host " - cron_get_task Get task details"
|
|
88
|
+
Write-Host ""
|
|
89
|
+
Write-Host "Restart Claude Code to load the MCP server" -ForegroundColor Yellow
|
|
90
|
+
Write-Host ""
|
|
91
|
+
Write-Host "Test the installation by asking Claude:" -ForegroundColor Cyan
|
|
92
|
+
Write-Host ' "Show me my cron-claude status"' -ForegroundColor White
|
|
93
|
+
Write-Host ""
|
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@patrick-rodgers/cron-claude",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Scheduled Claude task execution system - cron jobs for Claude",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"cron-claude-mcp": "./dist/mcp-server.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "tsc",
|
|
11
|
+
"dev": "tsc --watch",
|
|
12
|
+
"mcp": "node dist/mcp-server.js",
|
|
13
|
+
"test": "echo \"Tests coming soon\"",
|
|
14
|
+
"prepack": "npm run build"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"claude",
|
|
18
|
+
"automation",
|
|
19
|
+
"cron",
|
|
20
|
+
"scheduler",
|
|
21
|
+
"windows"
|
|
22
|
+
],
|
|
23
|
+
"author": "Patrick Rodgers",
|
|
24
|
+
"license": "MIT",
|
|
25
|
+
"files": [
|
|
26
|
+
"dist/",
|
|
27
|
+
"README.md",
|
|
28
|
+
"LICENSE",
|
|
29
|
+
"install.ps1",
|
|
30
|
+
"uninstall.ps1"
|
|
31
|
+
],
|
|
32
|
+
"repository": {
|
|
33
|
+
"type": "git",
|
|
34
|
+
"url": "https://github.com/patrick-rodgers/cron-claude.git"
|
|
35
|
+
},
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"@modelcontextprotocol/sdk": "^1.0.4",
|
|
38
|
+
"commander": "^12.0.0",
|
|
39
|
+
"gray-matter": "^4.0.3",
|
|
40
|
+
"node-cron": "^3.0.3",
|
|
41
|
+
"node-notifier": "^10.0.1"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@types/node": "^20.11.0",
|
|
45
|
+
"@types/node-cron": "^3.0.11",
|
|
46
|
+
"@types/node-notifier": "^8.0.5",
|
|
47
|
+
"typescript": "^5.3.3"
|
|
48
|
+
},
|
|
49
|
+
"engines": {
|
|
50
|
+
"node": ">=18.0.0"
|
|
51
|
+
}
|
|
52
|
+
}
|
package/uninstall.ps1
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
#!/usr/bin/env pwsh
|
|
2
|
+
<#
|
|
3
|
+
.SYNOPSIS
|
|
4
|
+
Uninstall cron-claude MCP server from Claude Code configuration
|
|
5
|
+
|
|
6
|
+
.DESCRIPTION
|
|
7
|
+
This script removes the cron-claude MCP server from Claude Code configuration.
|
|
8
|
+
It does not delete task files or logs.
|
|
9
|
+
|
|
10
|
+
.EXAMPLE
|
|
11
|
+
.\uninstall.ps1
|
|
12
|
+
#>
|
|
13
|
+
|
|
14
|
+
$ErrorActionPreference = "Stop"
|
|
15
|
+
|
|
16
|
+
Write-Host "Uninstalling cron-claude MCP server..." -ForegroundColor Cyan
|
|
17
|
+
|
|
18
|
+
# Get Claude Code config
|
|
19
|
+
$ClaudeConfigDir = Join-Path $env:USERPROFILE ".claude"
|
|
20
|
+
$ClaudeConfigFile = Join-Path $ClaudeConfigDir "config.json"
|
|
21
|
+
|
|
22
|
+
if (-not (Test-Path $ClaudeConfigFile)) {
|
|
23
|
+
Write-Host "No Claude config found. Nothing to uninstall." -ForegroundColor Yellow
|
|
24
|
+
exit 0
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
# Read existing config
|
|
28
|
+
$config = Get-Content $ClaudeConfigFile -Raw | ConvertFrom-Json
|
|
29
|
+
|
|
30
|
+
# Check if cron-claude exists
|
|
31
|
+
if (-not $config.mcpServers."cron-claude") {
|
|
32
|
+
Write-Host "cron-claude MCP server not found in config. Nothing to uninstall." -ForegroundColor Yellow
|
|
33
|
+
exit 0
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
# Convert to hashtable and remove cron-claude
|
|
37
|
+
$configHash = @{
|
|
38
|
+
mcpServers = @{}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
foreach ($property in $config.mcpServers.PSObject.Properties) {
|
|
42
|
+
if ($property.Name -ne "cron-claude") {
|
|
43
|
+
$configHash.mcpServers[$property.Name] = $property.Value
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
# Write config back
|
|
48
|
+
$configHash | ConvertTo-Json -Depth 10 | Set-Content $ClaudeConfigFile -Encoding UTF8
|
|
49
|
+
|
|
50
|
+
Write-Host ""
|
|
51
|
+
Write-Host "✓ Successfully uninstalled cron-claude MCP server!" -ForegroundColor Green
|
|
52
|
+
Write-Host ""
|
|
53
|
+
Write-Host "Restart Claude Code for changes to take effect" -ForegroundColor Yellow
|
|
54
|
+
Write-Host ""
|
|
55
|
+
Write-Host "Note: Task files and logs have NOT been deleted." -ForegroundColor Gray
|
|
56
|
+
Write-Host "To remove completely:" -ForegroundColor Gray
|
|
57
|
+
Write-Host " - Delete task files: $PSScriptRoot\tasks\" -ForegroundColor Gray
|
|
58
|
+
Write-Host " - Delete config: $env:USERPROFILE\.cron-claude\" -ForegroundColor Gray
|
|
59
|
+
Write-Host ""
|