Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 22 additions & 39 deletions plugins/shared/skills/crons/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,63 +1,46 @@
---
name: using-crons
description: Use when the user needs to run something on a cadence or do anything that interacts with crons. Creates, modifies and deletes cron jobs that run on a cadence.
description: Use when the user needs to run something on a cadence or do anything that interacts with crons or scheduled jobs. Scheduled work runs through Major workflows — a cron trigger calling a route on the deployed app.
---

# Cron Jobs
# Scheduled Jobs (Workflows)

Scheduled jobs are configured via a `cron.json` file at the project root and handled by route endpoints in the application.
Scheduled work on Major is handled by **workflows**: graphs of steps run by the platform's workflow engine. A scheduled job is a workflow with a **cron trigger** and an **`app_call` step** that calls a route on the deployed app on a cadence.

## cron.json
The legacy `cron.json` system is retired — the file is no longer read on deploy, and existing crons were migrated to workflows automatically. If the project still has a `cron.json`, it has no effect and can be deleted.

Create `cron.json` at the project root:
## Your job: implement the route

```json
{
"version": "1",
"crons": [
{
"name": "daily-cleanup",
"description": "Removes expired sessions",
"url": "/api/crons/cleanup",
"schedule": "0 2 * * *"
}
]
From a coding session you build the app side only — an HTTP route that performs the work:

```typescript
// app/api/jobs/cleanup/route.ts
export async function POST() {
// ... remove expired sessions
return Response.json({ ok: true });
}
```

Fields:
How workflow calls reach the route:

- `name` — unique identifier for the job
- `description` — human-readable explanation (used for documentation)
- `url` — the route path the scheduler will POST to
- `schedule` — 5-field cron expression (see below)
- Calls go to the **deployed** app, so the app must be deployed before a workflow can call the route.
- Requests arrive authenticated as the Major user the workflow runs as (via a platform-signed app-call JWT) — the route needs no webhook access and the app does not need to be public.
- The step's configured input arrives as query params for GET/DELETE and as a JSON body for POST/PUT/PATCH.
- The response body becomes the step's output, available to later steps in the workflow.

## Schedule Format
## Creating the schedule

Use a 5-field cron expression. Do **not** include a seconds field.
Workflows are created and managed in the Major web app, not from this coding session. After building the route:

```
┌─ minute (0–59)
│ ┌─ hour (0–23)
│ │ ┌─ day of month (1–31)
│ │ │ ┌─ month (1–12)
│ │ │ │ ┌─ day of week (0–7, 0 and 7 = Sunday)
│ │ │ │ │
* * * * *
```
1. Tell the user to deploy so the route exists on the deployed app.
2. Point them to the **Workflows** page in the Major dashboard to create (or update) a workflow with a cron trigger and an `app_call` step targeting the route's method and path.

Common schedules:
Cron triggers use a 5-field cron expression (`minute hour day-of-month month day-of-week` — no seconds field) with an IANA timezone. Common schedules:

| Schedule | Expression |
| ---------------------- | ------------- |
| Every minute | `* * * * *` |
| Every 5 minutes | `*/5 * * * *` |
| Every hour | `0 * * * *` |
| Every day at 2 AM | `0 2 * * *` |
| Every Monday 9 AM | `0 9 * * 1` |
| 1st of month, midnight | `0 0 1 * *` |

## Notes

- You should tell the user after you've build the scheduled job that they need to deploy for the cron to take affect
- The user can see a list of all crons they have on the left hand side bar
Loading