npm package: @shrimp-kit/scheduler
Description: > Schedule engine supporting cron, interval, daily, weekly, and monthly tasks with hot-reload, catch-up, night mode, and file-based queuing.
Latest version: 0.1.0

# @shrimp-kit/scheduler

> Schedule engine supporting cron, interval, daily, weekly, and monthly tasks with hot-reload, catch-up, night mode, and file-based queuing.

## Install

```bash
bun add @shrimp-kit/scheduler
```

## Features

- **5 schedule types** — `daily`, `interval`, `weekly`, `monthly`, `cron`
- **Hot-reload** — Schedule file changes are auto-detected
- **Catch-up** — Missed tasks (e.g. after sleep/restart) are automatically executed
- **Night mode** — Different intervals during specified night hours
- **Once tasks** — Fire once then auto-disable
- **Active windows** — Restrict execution to specific time ranges
- **File-based queue** — Pending tasks persisted to JSON

## Usage

### Schedule File Format

```json
{
  "_version": 1,
  "tasks": [
    {
      "id": "health-check",
      "enabled": true,
      "description": "Run health check every 30 minutes",
      "schedule": {
        "type": "interval",
        "minutes": 30
      },
      "command": "check-health"
    },
    {
      "id": "morning-report",
      "enabled": true,
      "description": "Send morning report at 8:05",
      "schedule": {
        "type": "daily",
        "time": "08:05"
      },
      "command": "morning-report"
    },
    {
      "id": "weekly-backup",
      "enabled": true,
      "description": "Weekly backup on Monday",
      "schedule": {
        "type": "weekly",
        "day": "monday",
        "time": "03:00"
      },
      "script": "backup.py"
    },
    {
      "id": "dev-session",
      "enabled": true,
      "description": "Dev session every 4 hours, longer at night",
      "schedule": {
        "type": "interval",
        "hours": 4,
        "nightHours": ["00:00", "08:00"],
        "nightIntervalHours": 8
      },
      "command": "dev-work"
    }
  ]
}
```

### Starting the Scheduler

```typescript
import { Logger } from "@shrimp-kit/core";
import { Scheduler } from "@shrimp-kit/scheduler";

const logger = new Logger({ name: "my-agent", level: "info" });

const scheduler = new Scheduler({
  schedulePath: "./data/schedule.json",
  statePath: "./data/scheduler-state.json",
  queuePath: "./data/pending.json",
  pollInterval: 30, // seconds
  logger,
  onTaskQueued: async (taskId, command) => {
    console.log(`Task queued: ${taskId} -> ${command}`);
    // e.g., send command to terminal via SendInput
  },
  onScriptComplete: (taskId, success, output) => {
    console.log(`Script ${taskId}: ${success ? "OK" : "FAIL"}`);
  },
});

await scheduler.start();
// Scheduler now polls every 30s, evaluating and executing due tasks

// Later...
scheduler.stop();
```

### Task Evaluation

Use the evaluator directly for custom scheduling logic:

```typescript
import { isTaskDue } from "@shrimp-kit/scheduler";

const result = isTaskDue(
  { type: "interval", hours: 2 },
  { lastRun: "2026-03-08T10:00:00Z", lastSuccess: true, runCount: 5, failCount: 0 },
  new Date(),
);
// → { isDue: true, reason: "interval_elapsed" }
```

### State Management

```typescript
import { StateManager } from "@shrimp-kit/scheduler";

const state = new StateManager("./data/state.json", logger);
await state.load();

state.recordRun("task-id", true);
const taskState = state.getTaskState("task-id");
// → { lastRun: "2026-03-08T...", lastSuccess: true, runCount: 1, failCount: 0 }

await state.save();
```

### Task Queue

```typescript
import { TaskQueue } from "@shrimp-kit/scheduler";

const queue = new TaskQueue("./data/pending.json", logger);

await queue.enqueue("task-id", "run-backup");
const pending = await queue.drain();
// → [{ taskId: "task-id", command: "run-backup", queuedAt: "..." }]
```

## Schedule Config Options

| Field | Type | Description |
|-------|------|-------------|
| `type` | `"daily" \| "interval" \| "weekly" \| "monthly" \| "cron"` | Schedule type |
| `time` | `string` | Time of day `"HH:MM"` (daily/weekly/monthly) |
| `hours` | `number` | Interval hours |
| `minutes` | `number` | Interval minutes |
| `day` | `string` | Day of week (weekly) |
| `dayOfMonth` | `number` | Day of month 1-31 (monthly) |
| `cron` | `string` | Cron expression |
| `startAfter` | `string` | Active window start `"HH:MM"` |
| `stopBefore` | `string` | Active window end `"HH:MM"` |
| `once` | `boolean` | Fire once then auto-disable |
| `nightHours` | `[string, string]` | Night window `["HH:MM", "HH:MM"]` |
| `nightIntervalHours` | `number` | Longer interval during night |

## API Reference

See [`src/index.ts`](./src/index.ts) for all exports.