The Complete Production SOP: How to Deploy and Run Cloudflare R2 Object Storage with Zero Egress Fees in Autonomous AI Agents
Step-by-step SOP to integrate Cloudflare R2 S3-compatible storage in Claude Code, Codex, and Cursor. Fix signature errors and generate presigned URLs.
Technical Overview & Architectural Context
Autonomous coding agents like Claude Code, Codex, Cursor, and Windsurf frequently introduce critical misconfigurations when interacting with Cloudflare R2. Because R2 exposes an S3-compatible API, LLMs default to standard AWS S3 conventions—hallucinating AWS regions (e.g., configuring 'us-east-1' instead of Cloudflare's mandatory 'auto'), generating invalid authentication headers for custom endpoints, or failing to construct presigned upload URLs with matching host headers. Furthermore, agents often overlook CDN edge caching headers, negating R2's zero-egress advantage. The cloudflare-r2-s3-compatible-storage skill solves this by establishing strict procedural guardrails. It forces agents to utilize the deterministic Cloudflare R2 endpoint URI format (https://<account_id>.r2.cloudflarestorage.com), enforces region='auto', enforces signature version v4, and mandates explicit Cache-Control headers ('public, max-age=31536000, immutable') on immutable public assets. This ensures zero runtime configuration drift and deterministic client initialization across Python and Node.js environments.
Prerequisites & Environment Requirements
Verified Search Intents & Long-Tail Queries Solved
This operational tutorial is engineered to provide deterministic solutions for these developer search queries:
Step-by-Step Execution Playbook
Local Environment Setup & SKILL.md Mounting
Create the local skill manifest directory and inject verified procedural rules into the agent runtime.
Agent runtimes such as Claude Code, Codex, Cursor, and Windsurf scan root or global agent directories for procedural context. By placing the verified SKILL.md into your project's .agents/skills directory or runtime-specific skill repository, the agent automatically associates user triggers like 'setup cloudflare r2 bucket' and 'presigned url cloudflare r2' with explicit S3 endpoint configuration SOPs.
mkdir -p .agents/skills/cloudflare-r2-s3-compatible-storage && cat << 'EOF' > .agents/skills/cloudflare-r2-s3-compatible-storage/SKILL.md
---
name: "cloudflare-r2-s3-compatible-storage"
description: "Store and serve multimedia assets globally with 100% S3 API compatibility and zero egress charges."
metadata:
author: "Cloudflare"
version: "1.0.0"
runtime_compatibility:
- "codex"
- "claude-code"
- "cursor"
- "windsurf"
triggers:
- "setup cloudflare r2 bucket"
- "presigned url cloudflare r2"
- "connect s3 client to r2"
permissions:
fs_read: true
fs_write: "workspace"
shell_exec: false
net_access: false
---
# Cloudflare R2 Object Storage with Zero Egress Fees
Deploys Cloudflare R2: configuring buckets, generating S3-compatible API tokens, setting up custom domain public access, presigned upload URLs in Node/Python, and cache headers.
## When to Invoke
Invoke this skill whenever you need to:
- setup cloudflare r2 bucket
- presigned url cloudflare r2
- connect s3 client to r2
## Execution SOP & Rules
1. Initialize AWS S3 Client passing endpoint: https://<account_id>.r2.cloudflarestorage.com.
2. Always configure region as 'auto' (do NOT use standard AWS regions like us-east-1).
3. Use Signature Version v4 for authentication.
4. Connect custom domain under R2 Bucket Settings -> Public Access -> Custom Domains.
5. Set Cache-Control: public, max-age=31536000, immutable on static uploads to leverage edge cache.
EOF---
name: "cloudflare-r2-s3-compatible-storage"
description: "Store and serve multimedia assets globally with 100% S3 API compatibility and zero egress charges."
triggers:
- "setup cloudflare r2 bucket"
- "presigned url cloudflare r2"
- "connect s3 client to r2"
---
# Cloudflare R2 Object Storage with Zero Egress Fees
...Instruct Claude Code or Cursor to reference the skill using direct symlinks in multi-repository setups to save token overhead and eliminate redundant SKILL.md duplications.
Do not grant shell_exec: true in the skill YAML frontmatter unless strictly necessary; keeping shell_exec: false preserves a high security score (98/100) and keeps the agent from executing unvetted external scripts.
Environment Secrets & Dependency Validation
Configure R2 credentials in environment variables and install verified S3 client libraries.
R2 requires an Account ID, Access Key ID, and Secret Access Key. The skill enforces reading credentials via process.env or os.environ rather than hardcoding them into client initialization logic. We also install the official AWS SDK v3 for Node.js or boto3 for Python.
npm install @aws-sdk/client-s3 @aws-sdk/s3-request-presigner dotenv && cat << 'EOF' > .env.example
CLOUDFLARE_ACCOUNT_ID=your_cf_account_id
R2_ACCESS_KEY_ID=your_r2_access_key
R2_SECRET_ACCESS_KEY=your_r2_secret_key
R2_BUCKET_NAME=assets-bucket
R2_PUBLIC_DOMAIN=cdn.example.com
EOFimport { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';
import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
const accountId = process.env.CLOUDFLARE_ACCOUNT_ID!;
export const r2Client = new S3Client({
region: 'auto',
endpoint: `https://${accountId}.r2.cloudflarestorage.com`,
credentials: {
accessKeyId: process.env.R2_ACCESS_KEY_ID!,
secretAccessKey: process.env.R2_SECRET_ACCESS_KEY!,
},
});
export async function getPresignedUploadUrl(key: string, contentType: string): Promise<string> {
const command = new PutObjectCommand({
Bucket: process.env.R2_BUCKET_NAME!,
Key: key,
ContentType: contentType,
CacheControl: 'public, max-age=31536000, immutable',
});
return getSignedUrl(r2Client, command, { expiresIn: 3600 });
}Never allow your AI agent to output secret values into chat output; pass credentials as environment variables and instruct the agent to inspect .env.example instead of .env.
Leaving region blank or setting it to standard AWS 'us-east-1' causes authentication signature errors or DNS resolution failures against R2 endpoints.
Intent Matching & Trigger Invocation
Activate deterministic skill execution using explicit triggers.
Trigger the agent using the exact phrases declared in the SKILL.md manifest, such as 'connect s3 client to r2' or 'presigned url cloudflare r2'. The agent runtime detects the intent and loads the execution rules into its immediate reasoning context.
# In Claude Code CLI or Cursor Chat, prompt:
presigned url cloudflare r2: generate an upload endpoint for user avatar uploads with 15-minute expirationimport { getPresignedUploadUrl } from '../lib/r2';
export async function handleAvatarUpload(userId: string, mimeType: string) {
const fileKey = `avatars/${userId}-${Date.now()}.png`;
const uploadUrl = await getPresignedUploadUrl(fileKey, mimeType);
return {
uploadUrl,
publicUrl: `https://${process.env.R2_PUBLIC_DOMAIN}/${fileKey}`,
};
}Specify ContentType explicitly in both PutObjectCommand and client PUT requests to ensure Cloudflare edge cache evaluates the mime type accurately.
Failing to pass ContentType during presigned URL generation will cause Cloudflare R2 to reject the upload with 403 SignatureDoesNotMatch if the uploading client provides a Content-Type header.
Verification, Linting & Output Quality Gate
Execute automated self-healing checks and validation scripts before accepting agent deliverables.
Verify that the agent wrote compliant client initialization, preserved workspace boundaries, and successfully generated valid presigned upload links without syntax errors.
node -e "import('./lib/r2.js').then(() => console.log('R2 client initialized successfully')).catch(console.error)" && pnpm tsc --noEmit#!/usr/bin/env bash
set -euo pipefail
echo "Validating R2 client environment..."
[ -z "${CLOUDFLARE_ACCOUNT_ID:-}" ] && { echo "CLOUDFLARE_ACCOUNT_ID missing"; exit 1; }
[ -z "${R2_ACCESS_KEY_ID:-}" ] && { echo "R2_ACCESS_KEY_ID missing"; exit 1; }
echo "Environment variables validated."Add git diff inspection to the agent's final checklist to verify no sensitive credentials or keys were staged during code generation.
R2 presigned URLs generated with a custom domain instead of the R2 API endpoint will fail to sign correctly unless configured through Cloudflare Workers.
Real-World Scenario: Direct-to-R2 Multimedia Upload Service with Edge Caching
“connect s3 client to r2 and create a secure presigned upload service for high-resolution video assets. Ensure uploaded assets have immutable edge caching headers and construct public URLs using our custom domain cdn.company.com.”
Runtime Troubleshooting & Failure Modes
Root Cause: The AWS SDK initialized with region 'us-east-1' or default AWS endpoints, causing AWS Signature Version 4 to sign against the wrong host or region header mismatching Cloudflare's required 'auto' configuration.
const s3 = new S3Client({ region: 'auto', endpoint: `https://${process.env.CLOUDFLARE_ACCOUNT_ID}.r2.cloudflarestorage.com` });Root Cause: The agent attempted to invoke Cloudflare R2 using AWS SDK v2 or an outdated S3 wrapper without SigV4 enabled.
npm install @aws-sdk/client-s3@latest && rm -rf node_modules/aws-sdkFrequently Asked Questions (Cloudflare R2 Object Storage with Zero Egress Fees SOP)
Q:Can I use Cloudflare R2 Object Storage with Zero Egress Fees across Codex, Claude Code, and Cursor simultaneously?
Yes. The skill conforms to the universal SKILL.md specification. Whether operating in Claude Code CLI via .agents/skills, Cursor IDE agent mode, or Codex workflows, the trigger definitions and procedural rules execute consistently.
Q:Why does Cloudflare R2 require region 'auto' instead of standard AWS regions?
Cloudflare R2 runs on a global Anycast network that routes storage traffic automatically to the nearest datacenter. Providing 'auto' satisfies the S3 SDK's region requirement while preventing signature validation errors.
Q:How does Cloudflare R2 Object Storage with Zero Egress Fees prevent context window overflow during long agent sessions?
By establishing concise procedural boundaries and deterministic validation gates in SKILL.md rather than polluting system prompts with redundant rules, the agent retains maximum context for your application code.
Ready to equip your autonomous agent with Cloudflare R2 Object Storage with Zero Egress Fees?
Copy the complete audited SKILL.md specification or download the 1-click zip bundle directly from our verified registry.