/vercel-schedules
Vercel Schedules guidance — run a private function, route, or Vercel Queues topic on a cron cadence or once at a set time. Covers static schedules in vercel.json, dynamic per-user schedules with @vercel/schedules, handleSchedule, the vercel schedules CLI, environments, jitter,
Claude Code
$ npx -y skills add vercel/vercel-plugin --skill vercel-schedules --agent claude-code
Codex
$ npx skills add vercel/vercel-plugin --skill vercel-schedules -a codex -y
Cursor
$ npx skills add vercel/vercel-plugin --skill vercel-schedules -a cursor -y
Gemini CLI
$ npx skills add vercel/vercel-plugin --skill vercel-schedules -a gemini-cli -y
GitHub Copilot
$ npx skills add vercel/vercel-plugin --skill vercel-schedules -a github-copilot -y
OpenCode
$ npx skills add vercel/vercel-plugin --skill vercel-schedules -a opencode -y
Windsurf
$ npx skills add vercel/vercel-plugin --skill vercel-schedules -a windsurf -y
SKILL.md
vercel-schedules.SKILL.mdname: vercel-schedules
description: Vercel Schedules guidance — run a private function, route, or Vercel Queues topic on a cron cadence or once at a set time. Covers static schedules in vercel.json, dynamic per-user schedules with @vercel/schedules, handleSchedule, the vercel schedules CLI, environments, jitter, and migrating from Cron Jobs. Use when adding scheduled or recurring work, one-time reminders, or replacing `crons`.
summary: "Vercel Schedules replaces Cron Jobs. Static schedules go in vercel.json under `schedules` and target a private `function` (with an `experimentalTriggers: [{ type: 'schedule/v1beta' }]` trigger; the default), a queue `topic`, or a public `path` (only to migrate Cron Jobs without code changes). Dynamic schedules come from `Schedules.create()` in `@vercel/schedules` or `vercel schedules create`, target queue topics only, and support one-time runs, payloads, and namespaces. Wrap function handlers in `handleSchedule`; make handlers idempotent with `executionId`."
metadata:
priority: 6
docs:
- "https://vercel.com/docs/schedules"
- "https://vercel.com/docs/schedules/quickstart"
- "https://vercel.com/docs/schedules/handle-runs"
- "https://vercel.com/docs/schedules/configuration"
- "https://vercel.com/docs/schedules/sdk"
- "https://vercel.com/docs/cli/schedules"
sitemap: "https://vercel.com/sitemap.xml"
pathPatterns:
- 'vercel.json'
- 'app/api/schedules/**'
- 'src/app/api/schedules/**'
- 'api/schedules/**'
- 'lib/schedules.*'
- 'src/lib/schedules.*'
- 'lib/schedules/**'
- 'src/lib/schedules/**'
bashPatterns:
- '\bnpm\s+(install|i|add)\s+[^\n]*@vercel/schedules\b'
- '\bpnpm\s+(install|i|add)\s+[^\n]*@vercel/schedules\b'
- '\bbun\s+(install|i|add)\s+[^\n]*@vercel/schedules\b'
- '\byarn\s+add\s+[^\n]*@vercel/schedules\b'
- '\b(vercel|vc)\s+schedules\b'
importPatterns:
- "@vercel/schedules"
promptSignals:
phrases:
- "vercel schedules"
- "@vercel/schedules"
- "handleSchedule"
- "scheduled job"
- "scheduled jobs"
- "scheduled task"
- "recurring job"
- "one-time schedule"
- "migrate cron jobs"
allOf:
- [vercel, schedule]
- [vercel, cron]
- [run, every, hour]
- [run, every, day]
- [run, every, night]
- [send, reminder, later]
- [per, user, schedule]
- [schedule, each, user]
- [vercel, every]
anyOf:
- "schedule"
- "cron"
- "recurring"
- "nightly"
- "hourly"
- "timezone"
- "reminder"
noneOf:
- "schedule a meeting"
- "calendar event"
- "deployment schedule"
- "release schedule"
minScore: 6
retrieval:
aliases:
- schedules
- cron
- cron jobs
- scheduled functions
- recurring jobs
- one-time jobs
intents:
- run code on a schedule
- run a function every hour
- send a reminder at a specific time
- create a schedule for each user
- migrate cron jobs to schedules
- pause or run a schedule now
entities:
- Vercel Schedules
- "@vercel/schedules"
- handleSchedule
- schedule/v1beta
- Schedules.create
- vercel schedules
chainTo:
-
pattern: 'from\s+[''"](node-cron|cron|croner|node-schedule|agenda)[''"]|cron\.schedule\('
targetSkill: vercel-schedules
message: 'In-process cron scheduling detected — it never runs on Vercel, because functions are not long-lived. Loading Vercel Schedules guidance.'
skipIfFileContains: '@vercel/schedules'
-
pattern: '"crons"\s*:'
targetSkill: vercel-schedules
message: 'Cron Jobs config detected — Schedules replaces Cron Jobs and adds timezones, private targets, and per-environment state. Loading Vercel Schedules guidance.'
skipIfFileContains: '"schedules"\s*:'Vercel Schedules
You are an expert in Vercel Schedules, which runs code on a recurring cron cadence or once at a specific time.
Choose static or dynamic
| | Static | Dynamic | |---|---|---| | **Defined in** | `vercel.json` `schedules` (or Build Output API `config.json`) | `@vercel/schedules` SDK or `vercel schedules` CLI | | **Takes effect** | When the deployment becomes current for its environment/branch | Immediately | | **Targets** | `function`, `path`, or `topic` | `topic` only | | **One-time runs** | No | Yes | | **Payload / namespace** | No / always `default` | Optional JSON (≤ 16 KB; 8 KB with `--local`) / any namespace | | **Update or delete** | Edit config and redeploy | SDK or CLI |
Use **static** for jobs that belong to the app (nightly cleanup, hourly sync). Use **dynamic** for jobs the app creates for users (a reminder per customer, a report at 09:00 in each tenant's timezone).
Choose a target
| Target | Use when | Retries | |---|---|---| | **`function`** (default) | Any new static schedule. The handler has no public URL, and only Vercel's scheduler can invoke it, so there's no secret to manage. | No | | **`topic`** | Failed runs must be retried, you need a payload, or the schedule is dynamic. | Yes, via Queues | | **`path`** | Only when migrating an existing Cron Job and you don't want to change any code. | No |
Prefer `function` over `path`. A `path` target exposes your handler to the public internet, and its only protection is a static `CRON_SECRET` that you have to store, check on every request, and rotate. A `function` target has neither problem. Don't pick `path` for new schedules, and don't pick it because a route "already exists". Wrapping the route in `handleSchedule` and adding the trigger is a small change.
If a failed run must be retried, target a queue topic.
Quickstart: private function on a static schedule
npm i @vercel/schedules
// api/cleanup.ts
import { handleSchedule } from '@vercel/schedules';
export const POST = handleSchedule(async (metadata) => {
console.log(`${metadata.name} run ${metadata.executionId} for ${metadata.schedRead more
name: vercel-schedules
description: Vercel Schedules guidance — run a private function, route, or Vercel Queues topic on a cron cadence or once at a set time. Covers static schedules in vercel.json, dynamic per-user schedules with @vercel/schedules, handleSchedule, the vercel schedules CLI, environments, jitter, and migrating from Cron Jobs. Use when adding scheduled or recurring work, one-time reminders, or replacing `crons`.
summary: "Vercel Schedules replaces Cron Jobs. Static schedules go in vercel.json under `schedules` and target a private `function` (with an `experimentalTriggers: [{ type: 'schedule/v1beta' }]` trigger; the default), a queue `topic`, or a public `path` (only to migrate Cron Jobs without code changes). Dynamic schedules come from `Schedules.create()` in `@vercel/schedules` or `vercel schedules create`, target queue topics only, and support one-time runs, payloads, and namespaces. Wrap function handlers in `handleSchedule`; make handlers idempotent with `executionId`."
metadata:
priority: 6
docs:
- "https://vercel.com/docs/schedules"
- "https://vercel.com/docs/schedules/quickstart"
- "https://vercel.com/docs/schedules/handle-runs"
- "https://vercel.com/docs/schedules/configuration"
- "https://vercel.com/docs/schedules/sdk"
- "https://vercel.com/docs/cli/schedules"
sitemap: "https://vercel.com/sitemap.xml"
pathPatterns:
- 'vercel.json'
- 'app/api/schedules/**'
- 'src/app/api/schedules/**'
- 'api/schedules/**'
- 'lib/schedules.*'
- 'src/lib/schedules.*'
- 'lib/schedules/**'
- 'src/lib/schedules/**'
bashPatterns:
- '\bnpm\s+(install|i|add)\s+[^\n]*@vercel/schedules\b'
- '\bpnpm\s+(install|i|add)\s+[^\n]*@vercel/schedules\b'
- '\bbun\s+(install|i|add)\s+[^\n]*@vercel/schedules\b'
- '\byarn\s+add\s+[^\n]*@vercel/schedules\b'
- '\b(vercel|vc)\s+schedules\b'
importPatterns:
- "@vercel/schedules"
promptSignals:
phrases:
- "vercel schedules"
- "@vercel/schedules"
- "handleSchedule"
- "scheduled job"
- "scheduled jobs"
- "scheduled task"
- "recurring job"
- "one-time schedule"
- "migrate cron jobs"
allOf:
- [vercel, schedule]
- [vercel, cron]
- [run, every, hour]
- [run, every, day]
- [run, every, night]
- [send, reminder, later]
- [per, user, schedule]
- [schedule, each, user]
- [vercel, every]
anyOf:
- "schedule"
- "cron"
- "recurring"
- "nightly"
- "hourly"
- "timezone"
- "reminder"
noneOf:
- "schedule a meeting"
- "calendar event"
- "deployment schedule"
- "release schedule"
minScore: 6
retrieval:
aliases:
- schedules
- cron
- cron jobs
- scheduled functions
- recurring jobs
- one-time jobs
intents:
- run code on a schedule
- run a function every hour
- send a reminder at a specific time
- create a schedule for each user
- migrate cron jobs to schedules
- pause or run a schedule now
entities:
- Vercel Schedules
- "@vercel/schedules"
- handleSchedule
- schedule/v1beta
- Schedules.create
- vercel schedules
chainTo:
-
pattern: 'from\s+[''"](node-cron|cron|croner|node-schedule|agenda)[''"]|cron\.schedule\('
targetSkill: vercel-schedules
message: 'In-process cron scheduling detected — it never runs on Vercel, because functions are not long-lived. Loading Vercel Schedules guidance.'
skipIfFileContains: '@vercel/schedules'
-
pattern: '"crons"\s*:'
targetSkill: vercel-schedules
message: 'Cron Jobs config detected — Schedules replaces Cron Jobs and adds timezones, private targets, and per-environment state. Loading Vercel Schedules guidance.'
skipIfFileContains: '"schedules"\s*:'Vercel Schedules
You are an expert in Vercel Schedules, which runs code on a recurring cron cadence or once at a specific time.
Choose static or dynamic
| | Static | Dynamic | |---|---|---| | **Defined in** | `vercel.json` `schedules` (or Build Output API `config.json`) | `@vercel/schedules` SDK or `vercel schedules` CLI | | **Takes effect** | When the deployment becomes current for its environment/branch | Immediately | | **Targets** | `function`, `path`, or `topic` | `topic` only | | **One-time runs** | No | Yes | | **Payload / namespace** | No / always `default` | Optional JSON (≤ 16 KB; 8 KB with `--local`) / any namespace | | **Update or delete** | Edit config and redeploy | SDK or CLI |
Use **static** for jobs that belong to the app (nightly cleanup, hourly sync). Use **dynamic** for jobs the app creates for users (a reminder per customer, a report at 09:00 in each tenant's timezone).
Choose a target
| Target | Use when | Retries | |---|---|---| | **`function`** (default) | Any new static schedule. The handler has no public URL, and only Vercel's scheduler can invoke it, so there's no secret to manage. | No | | **`topic`** | Failed runs must be retried, you need a payload, or the schedule is dynamic. | Yes, via Queues | | **`path`** | Only when migrating an existing Cron Job and you don't want to change any code. | No |
Prefer `function` over `path`. A `path` target exposes your handler to the public internet, and its only protection is a static `CRON_SECRET` that you have to store, check on every request, and rotate. A `function` target has neither problem. Don't pick `path` for new schedules, and don't pick it because a route "already exists". Wrapping the route in `handleSchedule` and adding the trigger is a small change.
If a failed run must be retried, target a queue topic.
Quickstart: private function on a static schedule
npm i @vercel/schedules
// api/cleanup.ts
import { handleSchedule } from '@vercel/schedules';
export const POST = handleSchedule(async (metadata) => {
console.log(`${metadata.name} run ${metadata.executionId} for ${metadata.schedComprehensive Vercel ecosystem plugin — relational knowledge graph, skills for every major product, specialized agents, and Vercel conventions. Turns any AI agent into a Vercel expert.
Other skills on vercel.
More skills from other plugins.
container
Use when running, building, or managing Linux containers on macOS, or when a task involves Docker, docker compose, Lima, Colima,…
frontend-forge-fe-oper…
Operate FrontendExtension (FE) resources in frontend-forge: create, update, rebuild, inspect package artifacts, download…
agent-advisor
Entry point for AI-agent work on AWS: pick a runtime, plan a migration for existing workloads, and build an executable POC — one…
agents-sdk
Build, debug, or review Cloudflare Agents SDK applications using the agents package.
Questions about vercel-schedules.
- Which coding agents can use vercel-schedules?
- vercel-schedules installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.

