Standalone cron job scheduler for Locus. Define recurring tasks with human-readable intervals, route output to multiple destinations (local files, Telegram, webhooks), and manage everything as a background PM2 process. Works independently of any platform adapter.
locus install cronOr install directly:
npm install @locusai/locus-cron# Add a cron job using natural language (AI-powered)
locus pkg cron add "check disk usage every hour"
# Or add with output routing
locus pkg cron add "run linter every 30 minutes" --route telegram
# Enable the scheduler
locus pkg cron enable
# Start the background worker
locus pkg cron startCron jobs are stored in .locus/config.json under packages.cron:
{
"packages": {
"cron": {
"enabled": true,
"batchWindowSeconds": 60,
"crons": [
{
"name": "disk-check",
"schedule": "1h",
"command": "df -h / | tail -1"
},
{
"name": "health-ping",
"schedule": "5m",
"command": "curl -s http://localhost:3000/health",
"routes": ["local", "telegram"]
},
{
"name": "code-review",
"schedule": "1d",
"command": "locus exec 'review recent changes and suggest improvements'",
"routes": ["telegram", "webhook:https://hooks.example.com/locus"]
}
]
}
}
}| Field | Type | Default | Description |
|---|---|---|---|
enabled |
boolean |
false |
Global on/off switch for the scheduler |
batchWindowSeconds |
number |
60 |
Batch window for co-scheduled notifications (seconds) |
crons |
CronJobConfig[] |
[] |
Array of cron job definitions |
| Field | Type | Required | Description |
|---|---|---|---|
name |
string |
Yes | Unique identifier (alphanumeric + hyphens) |
schedule |
string |
Yes | Human-readable interval (see below) |
command |
string |
Yes | Shell command or locus exec '<prompt>' for AI tasks |
routes |
string[] |
No | Output destinations (defaults to ["local"]) |
Instead of cron expressions, schedules use simple human-readable intervals:
| Format | Meaning | Example |
|---|---|---|
<n>s |
Every n seconds | 30s |
<n>m |
Every n minutes | 5m |
<n>h |
Every n hours | 1h |
<n>d |
Every n days | 1d |
Minimum interval is 10 seconds.
# Add a job from natural language (AI interprets schedule + command)
locus pkg cron add "check linter errors every hour"
# Add with output routing
locus pkg cron add "monitor API health every 5 minutes" --route telegram
# List all configured cron jobs
locus pkg cron list
# Remove a job by name
locus pkg cron remove disk-check
# Enable/disable the scheduler globally
locus pkg cron enable
locus pkg cron disable# Start cron worker in background (via PM2)
locus pkg cron start
# Stop the cron worker
locus pkg cron stop
# Restart the cron worker
locus pkg cron restart
# Remove the cron worker from PM2
locus pkg cron delete
# Check worker process status
locus pkg cron status
# View last 50 lines of logs (default)
locus pkg cron logs
# View last 100 lines of logs
locus pkg cron logs 100
# Run worker in foreground (useful for development)
locus pkg cron workerThe add command uses AI to interpret natural language into structured cron jobs:
locus pkg cron add "check disk usage every hour"
# β name: "disk-check", schedule: "1h", command: "df -h /"
locus pkg cron add "run tests every 30 minutes"
# β name: "run-tests", schedule: "30m", command: "npm test"
locus pkg cron add "review code quality daily" --route telegram
# β name: "code-review", schedule: "1d", command: "locus exec 'review code quality...'"Development-oriented tasks (review, check, analyze, lint, test) automatically use locus exec '<prompt>' to leverage AI.
Cron job results can be routed to multiple destinations simultaneously. Each job can specify its own routes array.
Writes output to .locus/cron/<job-name>/output.log:
[2026-03-08T10:00:00.000Z] [OK] /dev/sda1 50G 20G 28G 42% /
[2026-03-08T10:05:00.000Z] [EXIT 1] curl: (7) Failed to connect
Sends formatted messages to configured Telegram chats:
{
"routes": ["telegram"]
}Requires packages.telegram.botToken and packages.telegram.chatIds in your Locus config. Messages are formatted with MarkdownV2 and include job name, command, status, schedule, and output. Long output is truncated at 3500 characters.
POSTs results as JSON to any URL:
{
"routes": ["webhook:https://hooks.example.com/locus"]
}Payload format:
{
"jobId": "disk-check",
"command": "df -h /",
"output": "/dev/sda1 50G 20G 28G 42% /",
"exitCode": 0,
"timestamp": "2026-03-08T10:00:00.000Z",
"schedule": "1h"
}Combine routes to send results to multiple destinations:
{
"routes": ["local", "telegram", "webhook:https://hooks.example.com/locus"]
}When multiple cron jobs fire at similar times, the batcher groups their results to prevent notification spam. This applies to external adapters (Telegram, webhook) β local file logging always writes immediately.
- Batch window: Configurable via
batchWindowSeconds(default: 60 seconds) - Per-route batching: Results for the same route are combined into a single message
- Retry logic: Automatic retry after 5 seconds on adapter failure, with fallback to local logging
- Graceful degradation: One adapter failure doesn't block others
The package exports its scheduler and utilities for use in other packages:
import { CronScheduler, parseSchedule, formatInterval } from "@locusai/locus-cron";
// Parse a human-readable schedule to milliseconds
parseSchedule("30m"); // β 1800000
parseSchedule("1h"); // β 3600000
parseSchedule("bad"); // β null
// Format milliseconds back to human-readable
formatInterval(1800000); // β "30m"
// Use the scheduler directly
const scheduler = new CronScheduler(
{
enabled: true,
crons: [
{ name: "my-job", schedule: "5m", command: "echo hello" }
],
},
process.cwd()
);
scheduler.start();
scheduler.getStatus(); // β { running: true, cronCount: 1, crons: [...] }
scheduler.stop();import type {
CronJobConfig,
CronConfig,
CronJobResult,
ActiveCron,
CronSchedulerStatus,
OutputAdapter,
} from "@locusai/locus-cron";- The cron worker reads configuration from
packages.cronin.locus/config.json - Each cron job runs immediately on startup, then repeats at the configured interval
- Shell commands execute with a 30-second timeout in the project root directory
- Results are routed through the configured output adapters
- The result batcher groups co-scheduled notifications to prevent spam
- The worker runs as a PM2 background process with graceful SIGINT/SIGTERM shutdown
- PM2 heartbeat integration monitors worker health
| Package | Description |
|---|---|
@locusai/locus-pm2 |
PM2 process management used by this package |
@locusai/sdk |
SDK for building community packages |
@locusai/locus-gateway |
Channel-agnostic message gateway |
@locusai/locus-telegram |
Telegram platform adapter |