Skip to content
Development
Skill

/cloudflare-r2

Cloudflare R2 S3-compatible object storage. Use for buckets, uploads, CORS, presigned URLs, or encountering R2_ERROR, CORS failures, multipart issues.

From plugin
secondsky-claude-skills
219183 skills42 agents62 commands2 MCP
Install
$ npx -y skills add secondsky/claude-skills --skill cloudflare-r2 --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/cloudflare-r2

Context preview

The summary Claude sees to decide when to auto-load this skill.

Cloudflare R2 S3-compatible object storage. Use for buckets, uploads, CORS, presigned URLs, or encountering R2_ERROR, CORS failures, multipart issues.

SKILL.md

cloudflare-r2.SKILL.md
name: cloudflare-r2
description: "Cloudflare R2 S3-compatible object storage. Use for buckets, uploads, CORS, presigned URLs, or encountering R2_ERROR, CORS failures, multipart issues."
license: MIT
metadata:
  version: "3.0.0"
  last_verified: "2025-12-27"
  production_tested: true
  token_savings: "~65%"
  errors_prevented: 12
  templates_included: 5
  references_included: 11
  agents_included: 5
  commands_included: 4
  scripts_included: 3
  wrangler_version: "4.81.0"
  workers_types_version: "4.20260408.0"
  aws4fetch_version: "1.0.20"
  keywords:
    - r2
    - r2 storage
    - cloudflare r2
    - r2 bucket
    - r2 upload
    - r2 download
    - r2 binding
    - object storage
    - s3 compatible
    - r2 cors
    - presigned urls
    - multipart upload
    - r2 api
    - r2 workers
    - file upload
    - asset storage
    - R2_ERROR
    - R2Bucket
    - r2 metadata
    - custom metadata
    - http metadata
    - content-type
    - cache-control
    - aws4fetch
    - s3 client
    - bulk delete
    - r2 list
    - storage class

Cloudflare R2 Object Storage

**Status**: Production Ready ✅ | **Last Verified**: 2025-12-27 | **v3.0.0**

**Contents**: [Quick Start](#quick-start-5-minutes) • [New Features](#new-r2-features-2025) • [Core R2 API](#core-r2-workers-api-quick-reference) • [Critical Rules](#critical-rules) • [Agents & Commands](#available-agents--commands) • [References](#when-to-load-references)

---

Quick Start (5 Minutes)

1. Create R2 Bucket

bunx wrangler r2 bucket create my-bucket

**Bucket naming:** 3-63 chars, lowercase, numbers, hyphens only

2. Configure Binding

Add to `wrangler.jsonc`:

{
  "name": "my-worker",
  "main": "src/index.ts",
  "compatibility_date": "2025-10-11",
  "r2_buckets": [
    {
      "binding": "MY_BUCKET",          // env.MY_BUCKET
      "bucket_name": "my-bucket",      // Actual bucket
      "preview_bucket_name": "my-bucket-preview"  // Optional: dev bucket
    }
  ]
}

**CRITICAL:** `binding` = code access name, `bucket_name` = actual R2 bucket

3. Basic Upload/Download

import { Hono } from 'hono';

type Bindings = {
  MY_BUCKET: R2Bucket;
};

const app = new Hono<{ Bindings: Bindings }>();

// Upload
app.put('/upload/:filename', async (c) => {
  const filename = c.req.param('filename');
  const body = await c.req.arrayBuffer();

  const object = await c.env.MY_BUCKET.put(filename, body, {
    httpMetadata: {
      contentType: c.req.header('content-type') || 'application/octet-stream',
    },
  });

  return c.json({
    success: true,
    key: object.key,
    size: object.size,
  });
});

// Download
app.get('/download/:filename', async (c) => {
  const object = await c.env.MY_BUCKET.get(c.req.param('filename'));

  if (!object) {
    return c.json({ error: 'Not found' }, 404);
  }

  return new Response(object.body, {
    headers: {
      'Content-Type': object.httpMetadata?.contentType || 'application/octet-stream',
      'ETag': object.httpEtag,
    },
  });
});

export default app;

**Load `references/setup-guide.md` for complete setup walkthrough.**

---

New R2 Features (2025)

**🆕 R2 SQL Integration** - Query CSV/Parquet/JSON data with distributed SQL. Analytics without ETL. **Load `references/r2-sql-integration.md`**

**🆕 Data Catalog (Apache Iceberg)** - Table versioning, time-travel queries, schema evolution. Spark/Snowflake integration. **Load `references/data-catalog-iceberg.md`**

**🆕 Event Notifications** - Trigger Workers on object changes (upload/delete). Automate image processing, backups, webhooks. **Load `references/event-notifications.md`**

**Advanced Features** - Storage classes, bucket locks (compliance), tus resumable uploads, SSE-C encryption. **Load `references/advanced-features.md`**

**Zero Trust Security** - Cloudflare Access integration with SSO, MFA, identity policies, audit logging. **Load `references/cloudflare-access-integration.md`**

**Performance Tuning** - Caching strategies, compression, range requests, ETags, monitoring best practices. **Load `references/performance-optimization.md`**

---

Core R2 Workers API - Quick Reference

put() - Upload Objects

await env.MY_BUCKET.put(key, data, options?)

Upload with metadata, prevent overwrites with `onlyIf`. **Load `references/workers-api.md`** for complete R2PutOptions.

get() - Download Objects

const object = await env.MY_BUCKET.get(key, options?)

Returns `R2ObjectBody | null`. Supports range requests, conditional operations. **Load `references/workers-api.md`** for read methods (text(), json(), arrayBuffer(), blob()).

head() - Get Metadata Only

const object = await env.MY_BUCKET.head(key)

Check existence, get size, etag, metadata without downloading body. Useful for validation and caching.

delete() - Delete Objects

await env.MY_BUCKET.delete(key | keys[])  // Single or bulk (max 1000)

Bulk delete up to 1000 keys in single call. Always succeeds (idempotent).

list() - List Objects

const listed = await env.MY_BUCKET.list(options?)

Pagination with cursor, prefix filtering, delimiter for folders. **Load `references/workers-api.md`** for R2ListOptions.

createMultipartUpload() - Large Files (>100MB)

const multipart = await env.MY_BUCKET.createMultipartUpload(key, options?)

For files >100MB. **Load `references/common-patterns.md`** for complete multipart workflow with part upload and completion.

**Load `references/workers-api.md` when**: Need complete API reference, interface definitions (R2Object, R2ObjectBody, R2PutOptions, R2GetOptions), conditional operations, checksums, or advanced options.

---

Critical Rules

Always Do ✅

1. **Set contentType on uploads** - Files will download as binary otherwise 2. **Use batch delete** for multiple objects (up to 1000 keys) 3. **Set cache headers** for static assets (`cacheControl`) 4. **Use presigned

Read more
Ships withsecondsky-claude-skills

145 production-ready skills for Claude Code CLI 🔌 Platform / Harness Support These plugins ship as Claude Code marketplace plugins (.claude-plugin/ manifests) and Codex CLI plugins (.codex-plugin/ manifests).

Get the whole plugin

Other skills on secondsky-claude-skills.