Back to Skills

Cloudflare Cron Triggers

Cloudflare Cron Triggers for scheduled Workers execution. Use for periodic tasks, scheduled jobs, or encountering handler not found, invalid cron expression, timezone errors.

cloudflare
By secondsky
21030Updated 5 days agoTypeScriptMIT

Skill Content

# Cloudflare Cron Triggers

**Status**: Production Ready ✅
**Last Updated**: 2025-11-25
**Dependencies**: cloudflare-worker-base (for Worker setup)
**Latest Versions**: wrangler@4.50.0, @cloudflare/workers-types@4.20251125.0

---

## Quick Start (5 Minutes)

### 1. Add Scheduled Handler to Your Worker

**src/index.ts:**

```typescript
export default {
  async scheduled(
    controller: ScheduledController,
    env: Env,
    ctx: ExecutionContext
  ): Promise<void> {
    console.log('Cron job executed at:', new Date(controller.scheduledTime));
    console.log('Triggered by cron:', controller.cron);

    // Your scheduled task logic here
    await doPeriodicTask(env);
  },
};
```

**Why this matters:**
- Handler must be named exactly `scheduled` (not `scheduledHandler` or `onScheduled`)
- Must be exported in default export object
- Must use ES modules format (not Service Worker format)

### 2. Configure Cron Trigger in Wrangler

**wrangler.jsonc:**

```jsonc
{
  "name": "my-scheduled-worker",
  "main": "src/index.ts",
  "compatibility_date": "2025-10-23",
  "triggers": {
    "crons": [
      "0 * * * *"  // Every hour at minute 0
    ]
  }
}
```

**CRITICAL:**
- Cron expressions use 5 fields: `minute hour day-of-month month day-of-week`
- All times are **UTC only** (no timezone conversion)
- Changes take **up to 15 minutes** to propagate globally

### 3. Test Locally

```bash
# Enable scheduled testing
bunx wrangler dev --test-scheduled

# In another terminal, trigger the scheduled handler
curl "http://localhost:8787/__scheduled?cron=0+*+*+*+*"

# View output in wrangler dev terminal
```

**Testing tips:**
- `/__scheduled` endpoint is only available with `--test-scheduled` flag
- Can pass any cron expression in query parameter
- Python Workers use `/cdn-cgi/handler/scheduled` instead

### 4. Deploy

```bash
npm run deploy
# or
bunx wrangler deploy
```

**After deployment:**
- Changes may take up to 15 minutes to propagate
- Check dashboard: Workers & Pages > [Your Worker] > **Cron Triggers**
- View past executions in **Logs** tab

---

## When to Load References

**Load immediately when user mentions**:

- `cron-expressions-reference.md` → "cron syntax", "schedule format", "expression", "minute hour day", "every X minutes"
- `common-patterns.md` → "examples", "use cases", "patterns", "real-world", "database cleanup", "report generation", "how to"
- `integration-patterns.md` → "implement", "Hono", "multiple triggers", "bindings", "workflows", "error handling"
- `wrangler-config.md` → "configuration", "wrangler.jsonc", "multiple crons", "environment-specific", "dev staging production"
- `testing-guide.md` → "test", "local development", "__scheduled", "unit test", "curl", "debugging"

**Load proactively when**:
- Building new scheduled task → Load `integration-patterns.md`
- Configuring wrangler.jsonc → Load `wrangler-config.md`
- Debugging cron expression → Load `cron-expressions-reference.md`
- Testing locally → Load `testing-guide.md`
- Looking for examples → Load `common-patterns.md`

---

## Cron Expression Syntax

### Five-Field Format

```
* * * * *
│ │ │ │ │
│ │ │ │ └─── Day of Week (0-6, Sunday=0)
│ │ │ └───── Month (1-12)
│ │ └─────── Day of Month (1-31)
│ └───────── Hour (0-23)
└─────────── Minute (0-59)
```

### Special Characters

| Character | Meaning | Example |
|-----------|---------|---------|
| `*` | Every | `* * * * *` = every minute |
| `,` | List | `0,30 * * * *` = every hour at :00 and :30 |
| `-` | Range | `0 9-17 * * *` = every hour from 9am-5pm |
| `/` | Step | `*/15 * * * *` = every 15 minutes |

### Common Patterns

```bash
# Every minute
* * * * *

# Every 5 minutes
*/5 * * * *

# Every 15 minutes
*/15 * * * *

# Every hour at minute 0
0 * * * *

# Every hour at minute 30
30 * * * *

# Every 6 hours
0 */6 * * *

# Every day at midnight (00:00 UTC)
0 0 * * *

# Every day at noon (12:00 UTC)
0 12 * * *

# Every day at 3:30am UTC
30 3 * * *

# Every Monday at 9am UTC
0 9 * * 1

# Every weekday at 9am UTC
0 9 * * 1-5

# Every Sunday at midnight UTC
0 0 * * 0

# First day of every month at midnight UTC
0 0 1 * *

# Twice a day (6am and 6pm UTC)
0 6,18 * * *

# Every 30 minutes during business hours (9am-5pm UTC, weekdays)
*/30 9-17 * * 1-5
```

**CRITICAL: UTC Timezone Only**
- All cron triggers execute on **UTC time**
- No timezone conversion available
- Convert your local time to UTC manually
- Example: 9am PST = 5pm UTC (next day during DST)

---

## ScheduledController Interface

```typescript
interface ScheduledController {
  readonly cron: string;           // The cron expression that triggered this execution
  readonly type: string;           // Always "scheduled"
  readonly scheduledTime: number;  // Unix timestamp (ms) when scheduled
}
```

### Properties

#### `controller.cron` (string)

The cron expression that triggered this execution.

```typescript
export default {
  async scheduled(controller: ScheduledController, env: Env): Promise<void> {
    console.log(`Triggered by: ${controller.cron}`);
    // Output: "Triggered by: 0 * * * *"
  },
};
```

**Use case:** Differentiate between multiple cron schedules (see Multiple Cron Triggers pattern).

#### `controller.type` (string)

Always returns `"scheduled"` for cron-triggered executions.

```typescript
if (controller.type === 'scheduled') {
  // This is a cron-triggered execution
}
```

#### `controller.scheduledTime` (number)

Unix timestamp (milliseconds since epoch) when this execution was scheduled to run.

```typescript
export default {
  async scheduled(controller: ScheduledController): Promise<void> {
    const scheduledDate = new Date(controller.scheduledTime);
    console.log(`Scheduled for: ${scheduledDate.toISOString()}`);
    // Output: "Scheduled for: 2025-10-23T15:00:00.000Z"
  },
};
```

**Note:** This is the **scheduled** time, not the actual execution time. Due to system load, actual execution may be slightly delayed (usually <1 second).

---

## Execution Context

```typescript
export default {
  async scheduled(
    controller: ScheduledController,
    env: Env,
    ctx: ExecutionContext  // ← Execution context
  ): Promise<void> {
    // Use ctx.waitUntil() for async operations that should complete
    ctx.waitUntil(logToAnalytics(env));
  },
};
```

### `ctx.waitUntil(promise: Promise<any>)`

Extends the execution context to wait for async operations to complete after the handler returns.

**Use cases:**
- Logging to external services
- Analytics tracking
- Cleanup operations
- Non-critical background tasks

```typescript
export default {
  async scheduled(controller: ScheduledController, env: Env, ctx: ExecutionContext): Promise<void> {
    // Critical task - must complete before handler exits
    await processData(env);

    // Non-critical tasks - can complete in background
    ctx.waitUntil(sendMetrics(env));
    ctx.waitUntil(cleanupOldData(env));
    ctx.waitUntil(notifySlack({ message: 'Cron completed' }));
  },
};
```

**Important:** First `waitUntil()` that fails will be reported as the status in dashboard logs.

---

## Integration Patterns

**6 production-ready cron patterns**:

1. **Standalone Worker with Cron** - Single scheduled function for background tasks (database cleanup, report generation)
2. **Hono + Cron Combination** - HTTP endpoints + scheduled tasks in one Worker, sharing bindings and reducing costs
3. **Multiple Cron Triggers** - Different schedules for different tasks using `controller.cron` to route execution
4. **Accessing Bindings** - Use D1, KV, R2, AI, Vectorize, Queues, Workflows, Durable Objects in scheduled functions
5. **Integrating with Workflows** - Trigger complex, long-running multi-step workflows on schedule
6. **Error Handling Best Practices** - Comprehensive error handling with retry logic, alerting (Slack/email), failure logging, and monitoring

**Load `references/integration-patterns.md` for complete implementations with code examples, configuration details, and best practices.**

---

## Wrangler Configuration

Add cron triggers to `wrangler.jsonc` in the `triggers.crons` array. Each trigger requires a `cron` expression. Supports multiple crons (Free: 3 max, Paid: higher limits) and environment-specific configurations for dev/staging/production deployments.

**Load `references/wrangler-config.md` for complete configuration examples including multiple triggers, environment-specific schedules, timezone handling, and removal procedures.**

---

## Testing & Development

Test scheduled functions locally using the `/__scheduled` endpoint by running `bunx wrangler dev --test-scheduled`, then triggering handlers with `curl "http://localhost:8787/__scheduled?cron=0+*+*+*+*"` (use `+` instead of spaces in cron expressions).

**Load `references/testing-guide.md` for complete testing strategies, local development setup, unit testing examples, integration testing patterns, and production monitoring techniques.**

---

## Green Compute

Run cron triggers only in data centers powered by renewable energy.

### Enable Green Compute

**Via Dashboard:**

1. Go to [Workers & Pages](https://dash.cloudflare.com/?to=/:account/workers-and-pages)
2. In **Account details** section, find **Compute Setting**
3. Click **Change**
4. Select **Green Compute**
5. Click **Confirm**

**Applies to:**
- All cron triggers in your account
- Reduces carbon footprint
- No additional cost
- May introduce slight delays in some regions

**How it works:**
- Cloudflare routes cron executions to green-powered data centers
- Uses renewable energy: wind, solar, hydroelectric
- Verified through Power Purchase Agreements (PPAs) and Renewable Energy Credits (RECs)

---

## Known Issues Prevention

This skill prevents **6** documented issues:

### Issue #1: Cron Changes Not Propagating

**Error:** Cron triggers updated in wrangler.jsonc but not executing

**Source:** [Cloudflare Docs - Cron Triggers](https://developers.cloudflare.com/workers/configuration/cron-triggers/)

**Why It Happens:**
- Changes to cron triggers take up to **15 minutes** to propagate globally
- Cloudflare network needs time to update edge nodes
- No instant propagation like regular deploys

**Prevention:**
- Wait 15 minutes after deploy before expecting execution
- Check dashboard: Workers & Pages > [Worker] > Cron Triggers
- Use `wrangler triggers deploy` for trigger-only changes

```bash
# If you only changed triggers (not code), use:
bunx wrangler triggers deploy

# Wait 15 minutes, then verify in dashboard
```

---

### Issue #2: Handler Does Not Export

**Error:** `Handler does not export a 'scheduled' method`

**Source:** Common deployment error

**Why It Happens:**
- Handler not named exactly `scheduled`
- Handler not exported in default export object
- Using Service Worker format instead of ES modules

**Prevention:**

```typescript
// ❌ Wrong: Incorrect handler name
export default {
  async scheduledHandler(controller, env, ctx) { }
};

// ❌ Wrong: Not in default export
export async function scheduled(controller, env, ctx) { }

// ✅ Correct: Named 'scheduled' in default export
export default {
  async scheduled(controller, env, ctx) { }
};
```

---

### Issue #3: UTC Timezone Confusion

**Error:** Cron runs at wrong time

**Source:** User expectation vs. reality

**Why It Happens:**
- All cron triggers run on **UTC time only**
- No timezone conversion available
- Users expect local timezone

**Prevention:**

Convert your local time to UTC manually:

```typescript
// Want to run at 9am PST (UTC-8)?
// 9am PST = 5pm UTC (17:00)
{
  "triggers": {
    "crons": ["0 17 * * *"]  // 9am PST = 5pm UTC
  }
}

// Want to run at 6pm EST (UTC-5)?
// 6pm EST = 11pm UTC (23:00)
{
  "triggers": {
    "crons": ["0 23 * * *"]  // 6pm EST = 11pm UTC
  }
}

// Remember: DST changes affect conversion!
// PST is UTC-8, PDT is UTC-7
```

**Tools:**
- [Time Zone Converter](https://www.timeanddate.com/worldclock/converter.html)
- [Cron Expression Generator](https://crontab.guru/)

---

### Issue #4: Invalid Cron Expression

**Error:** Cron doesn't execute, no error shown

**Source:** Silent validation failure

**Why It Happens:**
- Invalid cron syntax silently fails
- Validation happens at deploy, but may not be obvious
- Common mistakes: wrong field order, invalid ranges

**Prevention:**

```bash
# ❌ Wrong: Too many fields (6 fields instead of 5)
"crons": ["0 0 * * * *"]  # Has seconds field - not supported

# ❌ Wrong: Invalid minute range
"crons": ["65 * * * *"]  # Minute must be 0-59

# ❌ Wrong: Invalid day of week
"crons": ["0 0 * * 7"]  # Day of week is 0-6 (use 0 for Sunday)

# ✅ Correct: 5 fields, valid ranges
"crons": ["0 0 * * 0"]  # Sunday at midnight UTC
```

**Validation:**
- Use [Crontab Guru](https://crontab.guru/) to validate expressions
- Check wrangler deploy output for errors
- Test locally with `--test-scheduled`

---

### Issue #5: Missing ES Modules Format

**Error:** `Worker must use ES modules format`

**Source:** Legacy Service Worker format

**Why It Happens:**
- Scheduled handler requires ES modules format
- Old Service Worker format not supported
- Mixed format in codebase

**Prevention:**

```typescript
// ❌ Wrong: Service Worker format
addEventListener('scheduled', (event) => {
  event.waitUntil(handleScheduled(event));
});

// ✅ Correct: ES modules format
export default {
  async scheduled(controller, env, ctx) {
    await handleScheduled(controller, env, ctx);
  },
};
```

---

### Issue #6: CPU Time Limits Exceeded

**Error:** `CPU time limit exceeded`

**Source:** Long-running scheduled tasks

**Why It Happens:**
- Default CPU limit: 30 seconds
- Long-running tasks exceed limit
- No automatic timeout extension

**Prevention:**

**Option 1: Increase CPU limit in wrangler.jsonc**

```jsonc
{
  "limits": {
    "cpu_ms": 300000  // 5 minutes (max for Standard plan)
  }
}
```

**Option 2: Use Workflows for long-running tasks**

```typescript
// Instead of long task in cron:
export default {
  async scheduled(controller, env, ctx) {
    // Trigger Workflow that can run for hours
    await env.MY_WORKFLOW.create({
      params: { task: 'long-running-job' },
    });
  },
};
```

**Option 3: Break into smaller chunks**

```typescript
export default {
  async scheduled(controller, env, ctx) {
    // Process in batches
    const batch = await getNextBatch(env.DB);

    for (const item of batch) {
      await processItem(item);
    }

    // If more work, send to Queue for next batch
    const hasMore = await hasMoreWork(env.DB);
    if (hasMore) {
      await env.MY_QUEUE.send({ type: 'continue-processing' });
    }
  },
};
```

---

## Always Do ✅

1. **Use exact handler name** - Must be `scheduled`, not `scheduledHandler` or variants
2. **Use ES modules format** - Export in default object, not addEventListener
3. **Convert to UTC** - All cron times are UTC, convert from local timezone
4. **Wait 15 minutes** - Cron changes take up to 15 min to propagate
5. **Test locally first** - Use `wrangler dev --test-scheduled`
6. **Validate cron syntax** - Use [Crontab Guru](https://crontab.guru/)
7. **Handle errors gracefully** - Log, alert, and optionally re-throw
8. **Use ctx.waitUntil()** - For non-critical async operations
9. **Consider Workflows** - For tasks that need >30 seconds CPU time
10. **Monitor executions** - Check dashboard logs regularly

---

## Never Do ❌

1. **Never assume local timezone** - All crons run on UTC
2. **Never use 6-field cron expressions** - Cloudflare uses 5-field format (no seconds)
3. **Never rely on instant propagation** - Changes take up to 15 minutes
4. **Never use Service Worker format** - Must use ES modules format
5. **Never forget error handling** - Uncaught errors fail silently
6. **Never run CPU-intensive tasks without limit increase** - Default 30s limit
7. **Never use day-of-week 7** - Use 0 for Sunday (0-6 range only)
8. **Never deploy without testing** - Always test with `--test-scheduled` first
9. **Never ignore execution logs** - Dashboard shows past failures
10. **Never hardcode schedules for testing** - Use environment-specific configs

---

## Common Use Cases

**Load `references/common-patterns.md` for 10 real-world cron patterns including database cleanup, API data collection, daily reports generation, cache warming, monitoring & health checks, data synchronization, backup automation, sitemap generation, webhook processing, and scheduled notifications.**

---

## TypeScript Types

```typescript
// Scheduled event controller
interface ScheduledController {
  readonly cron: string;
  readonly type: string;
  readonly scheduledTime: number;
}

// Execution context
interface ExecutionContext {
  waitUntil(promise: Promise<any>): void;
  passThroughOnException(): void;
}

// Scheduled handler
export default {
  async scheduled(
    controller: ScheduledController,
    env: Env,
    ctx: ExecutionContext
  ): Promise<void>;
}
```

---

## Limits & Pricing

### Limits

| Feature | Free Plan | Paid Plan |
|---------|-----------|-----------|
| **Cron triggers per Worker** | 3 | Higher (check docs) |
| **CPU time per execution** | 10 ms (avg) | 30 seconds (default), 5 min (max) |
| **Wall clock time** | 30 seconds | 15 minutes |
| **Memory** | 128 MB | 128 MB |

### Pricing

Cron triggers use **Standard Workers pricing**:

- **Workers Paid Plan**: $5/month required
- **Requests**: $0.30 per million requests (after 10M free)
- **CPU Time**: $0.02 per million CPU-ms (after 30M free)

**Cron execution = 1 request**

**Example:**
- Cron runs every hour (24 times/day)
- 30 days × 24 executions = 720 executions/month
- Average 50ms CPU time per execution

**Cost:**
- Requests: 720 (well under 10M free)
- CPU time: 720 × 50ms = 36,000ms (under 30M free)
- **Total: $5/month (just subscription)**

**High frequency example:**
- Cron runs every minute (1440 times/day)
- 30 days × 1440 = 43,200 executions/month
- Still under free tier limits
- **Total: $5/month**

---

## Troubleshooting

### Issue: Cron not executing

**Possible causes:**
1. Changes not propagated yet (wait 15 minutes)
2. Invalid cron expression
3. Handler not exported correctly
4. Worker not deployed

**Solution:**

```bash
# Re-deploy
bunx wrangler deploy

# Wait 15 minutes

# Check dashboard
# Workers & Pages > [Worker] > Cron Triggers

# Check logs
# Workers & Pages > [Worker] > Logs > Real-time Logs
```

---

### Issue: Handler executes but fails

**Possible causes:**
1. Uncaught error in handler
2. CPU time limit exceeded
3. Missing environment bindings
4. Network timeout

**Solution:**

```typescript
export default {
  async scheduled(controller, env, ctx) {
    try {
      await yourTask(env);
    } catch (error) {
      // Log detailed error
      console.error('Handler failed:', {
        error: error.message,
        stack: error.stack,
        cron: controller.cron,
        time: new Date(controller.scheduledTime),
      });

      // Send alert
      ctx.waitUntil(sendAlert(error));

      // Re-throw to mark as failed
      throw error;
    }
  },
};
```

Check logs in dashboard for error details.

---

### Issue: Wrong execution time

**Cause:** UTC vs. local timezone confusion

**Solution:**

Convert your desired local time to UTC:

```typescript
// Want 9am PST (UTC-8)?
// 9am PST = 5pm UTC (17:00)

{
  "triggers": {
    "crons": ["0 17 * * *"]
  }
}
```

**Tools:**
- [World Clock Converter](https://www.timeanddate.com/worldclock/converter.html)
- Remember DST changes (PST vs PDT)

---

### Issue: Local testing not working

**Possible causes:**
1. Missing `--test-scheduled` flag
2. Wrong endpoint (should be `/__scheduled`)
3. Python Worker (use `/cdn-cgi/handler/scheduled`)

**Solution:**

```bash
# Correct: Start with flag
bunx wrangler dev --test-scheduled

# In another terminal
curl "http://localhost:8787/__scheduled?cron=0+*+*+*+*"
```

---

## Production Checklist

Before deploying cron triggers to production:

- [ ] Cron expression validated on [Crontab Guru](https://crontab.guru/)
- [ ] Handler named exactly `scheduled` in default export
- [ ] ES modules format used (not Service Worker)
- [ ] Local timezone converted to UTC
- [ ] Error handling implemented with logging
- [ ] Alerts configured for failures
- [ ] CPU limits increased if needed (`limits.cpu_ms`)
- [ ] Environment bindings tested
- [ ] Tested locally with `--test-scheduled`
- [ ] Deployment tested in staging environment
- [ ] Waited 15 minutes after deploy for propagation
- [ ] Verified execution in dashboard logs
- [ ] Monitoring and alerting configured
- [ ] Documentation updated with schedule details

---

## Related Documentation

- **Cloudflare Cron Triggers**: https://developers.cloudflare.com/workers/configuration/cron-triggers/
- **Scheduled Handler API**: https://developers.cloudflare.com/workers/runtime-apis/handlers/scheduled/
- **Cron Trigger Examples**: https://developers.cloudflare.com/workers/examples/cron-trigger/
- **Multiple Cron Triggers**: https://developers.cloudflare.com/workers/examples/multiple-cron-triggers/
- **Wrangler Triggers Command**: https://developers.cloudflare.com/workers/wrangler/commands/#triggers
- **Workers Pricing**: https://developers.cloudflare.com/workers/platform/pricing/
- **Workflows Integration**: https://developers.cloudflare.com/workflows/
- **Crontab Guru** (validator): https://crontab.guru/
- **Time Zone Converter**: https://www.timeanddate.com/worldclock/converter.html

---

**Last Updated**: 2025-10-23
**Version**: 1.0.0
**Maintainer**: Claude Skills Maintainers | maintainers@example.com

How to use

  1. Copy the skill content above
  2. Create a .claude/skills/claude-skills-cloudflare-cron-triggers directory in your project (or ~/.claude/skills/claude-skills-cloudflare-cron-triggers to use it in every project)
  3. Save the content as .claude/skills/claude-skills-cloudflare-cron-triggers/SKILL.md
  4. Claude Code loads it automatically when the task matches, or run /claude-skills-cloudflare-cron-triggers to invoke it directly

Claude Code Skills Collection

142 production-ready skills for Claude Code CLI

Version 3.6.3 | Last Updated: 2026-08-06

<div align="center">

🔌 Platform / Harness Support

These plugins ship as Claude Code marketplace plugins (.claude-plugin/ manifests) and Codex CLI plugins (.codex-plugin/ manifests). Other harnesses consume the same skills via skills.sh — the cross-harness bridge.

HarnessMarketplace supportHow to install
Claude CodeNative (federated)/plugin marketplace add secondsky/claude-skills, then /plugin install <name>@claude-skills
ZCodeNative (reads .claude-plugin/ manifests)Add this repo as a marketplace in the ZCode GUI
Codex CLINative (federated)codex plugin marketplace add secondsky/claude-skills, then /plugins in the Codex TUI
Cursor⚠️ Adaptation neededCursor has an official marketplace, but expects .cursor-plugin/plugin.json (UI "Add to Cursor") this repo does not generate yet. Use skills.sh.
opencode❌ No marketplacenpm plugins only (opencode.json plugin[]). Use skills.sh or vendor manually.
Gemini CLI❌ No marketplacegemini extensions install <url> only. Use skills.sh or vendor manually.
</div>

A curated collection of battle-tested skills for building modern web applications with Cloudflare, AI integrations, React, Tailwind, and more.


Quick Start

Marketplace Installation (Recommended)

# Add the marketplace
/plugin marketplace add https://github.com/secondsky/claude-skills

# Install individual skills as needed
/plugin install cloudflare-d1@claude-skills
/plugin install tailwind-v4-shadcn@claude-skills
/plugin install gemini-cli@claude-skills

See MARKETPLACE.md for complete catalog of all 142 skills.

Codex CLI Installation

This repo generates .codex-plugin/ manifests and a .agents/plugins/marketplace.json for all 142 plugins, so Codex CLI can install them natively:

# Add the marketplace (from GitHub)
codex plugin marketplace add secondsky/claude-skills

# Browse and install plugins in the Codex TUI
#   /plugins          # opens the plugin browser
#   Space             # enable/disable a plugin

Skills are auto-discovered from each plugin's skills/ directory — the same SKILL.md files Claude Code uses. Claude-specific slash commands and subagents are not carried into Codex (use Codex's /import command for that).


Installing with skills.sh

skills.sh is an open agent-skills registry and npx skills CLI (maintained by Vercel) that auto-detects your coding agent — Claude Code, Cursor, Codex, Copilot, Cline, opencode, and 70+ others — and installs each skill into the correct directory for that harness. It is the universal cross-harness path for harnesses without a marketplace (opencode, Gemini CLI) or where this repo's manifest format isn't generated yet (Cursor).

# Install one skill (auto-detects your agent)
npx skills add secondsky/claude-skills --skill cloudflare-d1

# Install several specific skills
npx skills add secondsky/claude-skills --skill cloudflare-d1 --skill tailwind-v4-shadcn

# Try a skill once without installing (pipes its prompt to your agent)
npx skills use secondsky/claude-skills@cloudflare-d1 | claude

# Target a specific agent explicitly
npx skills add secondsky/claude-skills --skill cloudflare-d1 --agent codex

# List what's installed, search, update, remove
npx skills ls -g
npx skills find cloudflare
npx skills update cloudflare-d1
npx skills remove cloudflare-d1

Bulk install note: npx skills add secondsky/claude-skills --all installs every discovered skill at once, but discovery walks skills.sh's standard container directories (skills/, .claude/skills/, …). This repo nests skills under plugins/<name>/skills/<skill>/, so --all may not pick up everything in one pass — install the skills you need by name with --skill, or run npx skills add secondsky/claude-skills -l to list what it finds.

Security scanning caveat

skills.sh runs every published skill through three scanners (Gen Agent Trust Hub, Socket, Snyk) plus an LLM-based meta-analyzer, and publishes the results at skills.sh/audits. The LLM analysis stage has been publicly shown (Trail of Bits, June 2026) to both miss genuinely malicious skills and flag unfamiliar version pins (e.g. newest dependency versions) as suspicious false positives. Treat skills.sh warnings as advisory, not authoritative — and verify against this repo's own version pins before acting on a warning.


Repository Structure

This repository contains 142 production-tested skills for Claude Code, each focused on a specific technology or capability.

Individual Skills: Each skill is a standalone unit with:

  • SKILL.md - Core knowledge and guidance
  • Templates - Working code examples
  • References - Extended documentation
  • Scripts - Helper utilities

Installation Options:

  1. Marketplace (recommended) - Install individual skills via /plugin install <name>@claude-skills
  2. Cross-harness - Install into any supported agent with npx skills add secondsky/claude-skills --skill <name> (see Installing with skills.sh)

Available Skills (142 Individual Skills)

Each skill is individually installable. Install only the skills you need.

Full Catalog: See MARKETPLACE.md for detailed listings.

Categories

CategorySkillsExamples
tooling24turborepo, plan-interview, code-review
frontend26nuxt-v4, nuxt-v5, tailwind-v4-shadcn, tanstack-query, nuxt-studio, maz-ui, threejs
cloudflare21cloudflare-d1, cloudflare-workers-ai, cloudflare-agents
api16api-design-principles, graphql-implementation
ai7gemini-cli, ml-model-training, tanstack-ai
web10hono-routing, firecrawl-scraper, web-performance
security6csrf-protection, xss-prevention, cybersecurity
mobile5react-native-app, react-native-skills
woocommerce4woocommerce-backend-dev
testing4vitest-testing, playwright-testing
design4design-review, design-system-creation
auth4better-auth
architecture3microservices-patterns, architecture-patterns
data2recommendation-engine, recommendation-system
cms2hugo, wordpress-plugin-core
database1drizzle-orm-d1
seo2seo-optimizer, seo-keyword-cluster-builder
documentation1technical-specification

How It Works

Auto-Discovery

Claude Code automatically checks ~/.claude/skills/ for relevant skills before planning tasks:

User: "Set up a Cloudflare Worker with D1 database"
           ↓
Claude: [Checks skills automatically]
           ↓
Claude: "Found cloudflare-d1 skills.
         These prevent 12 documented errors. Use them?"
           ↓
User: "Yes"
           ↓
Result: Production-ready setup, zero errors, ~65% token savings

Note: Due to token limits, not all skills may be visible at once. See ⚠️ Important: Token Limits below.

Skill Structure

Each plugin is a directory under plugins/<plugin-name>/ containing one or more skills:

plugins/[plugin-name]/
├── .claude-plugin/
│   └── plugin.json       # Plugin manifest (marketplace metadata)
├── README.md
├── skills/
│   └── [skill-name]/
│       ├── SKILL.md          # Core knowledge and guidance
│       ├── templates/        # Ready-to-copy templates
│       ├── scripts/          # Helper utilities
│       └── references/       # Extended documentation
└── (optional) agents/, commands/, hooks/

Recent Additions

July 2026

Offensive Security (new category):

  • cybersecurity — Unified OSS-only cybersecurity skill with progressive disclosure. Fuses 7 community skills (mukul975 business-logic/XSS/host-header/forced-browsing/open-redirect, rysweet/amplihack cybersecurity-analyst, Aradotso security-detections-mcp) ported to fully open-source tooling (OWASP ZAP, Dalfox, ffuf, Nuclei, mitmproxy, interact.sh, Semgrep, Sigma). Covers threat modeling (STRIDE/PASTA/VAST, MITRE ATT&CK), web-vuln testing, SAST, code audit, AI/LLM-app security, and detection engineering. Live-target testing is gated behind an authorization disclaimer; static analysis, code review, and threat modeling are always available. Cross-references the 5 existing defensive security plugins (csrf-protection, xss-prevention, vulnerability-scanning, security-headers-configuration, defense-in-depth-validation) for remediation. Integrates 20 Aradotso dev-security skills across 5 grouped reference docs.

May 2026

Supply Chain Security (cross-cutting):

  • dependency-upgrade expanded with Socket CLI integration — proactive malicious package detection, typosquatting alerts, and CI/CD security gates. New 418-line reference guide, 2 GitHub Actions templates, and expanded supply chain security comparison (3 tools)
  • 31 skills now include "Secure Installation" guidance — contextually-tailored security sections across all high-risk skill categories (scaffolding, MCP/agent SDKs, multi-provider installs, Docker, CI/CD). Covers 8 Bun skills, 5 Nuxt skills, 6 Cloudflare skills, 4 AI/agent skills, and 8 frontend/tooling skills
  • Supply chain security is now a first-class cross-cutting concern woven into the skill collection — not a standalone topic

February - April 2026

Full-Stack Frameworks:

  • nuxt-v5 (v1.0.0) - Full Nuxt 5 support with 4 skills (core, data, server, production), 3 diagnostic agents, and interactive setup wizard
  • threejs (v1.0.0) - 3D web graphics: scenes, geometries, shaders, animations, post-processing

Infrastructure:

  • JSON schema validation - Automated plugin.json validation with CI support
  • GitHub issue templates - Skill-specific issue templates for bug reports, feature requests, and submissions

Plugin Enhancements:

  • mutation-testing - Added Bun native runner support
  • dependency-upgrade - Added supply chain security content

December 2025 - January 2026

Frontend Expansion:

  • nuxt-studio (v1.0.0) - Visual CMS for Nuxt Content with live preview, OAuth auth, and R2 storage integration
  • maz-ui (v1.0.0) - 50+ Vue/Nuxt components with theming, i18n, form generation, and 14 composables

Developer Workflow:

  • plan-interview (v2.0.0) - Adaptive interview-driven spec generation with autonomous quality review
  • turborepo (v2.8.0) - Updated to official Vercel skill with enhanced monorepo build optimization

Mobile Development:

  • react-native-skills (v1.0.0) - React Native & Expo best practices with performance optimization patterns

Enhanced Authentication:

  • better-auth (v2.2.0) - Expanded to 18 framework integrations with 30+ authentication plugins

⚠️ Important: Token Limits

Skill Visibility Constraint

Claude Code has a 15,000 character limit for the total size of skill descriptions in the system prompt. This limit also applies to commands and agents.

What this means:

  • Not all 142 skills may be visible in Claude's context at once
  • Skills are loaded based on relevance and available token budget
  • You can verify how many skills Claude currently sees by asking: "How many skills do you see in your system prompt?"

Checking Visible Skills

To verify which skills are currently loaded:

# Ask Claude Code directly
"Check what skills/plugins you see in your system prompt"

Claude will report something like: "85 of 142 skills visible due to token limits"

Workaround: Increase Token Budget

You can double the headroom for s

View source on GitHub