# Pinme R2

Use when a PinMe Cloudflare Worker needs R2 object storage, including secure file or...

- Repository: https://github.com/glitternetwork/pinme (3753 stars)
- Category: DevOps
- License: MIT
- Last updated: 2026-09-12
- Runs scripts: no, instructions only

## Install

Claude Code: `npx skills add glitternetwork/pinme --skill pinme-r2 -g -a claude-code -y`
Codex: `npx skills add glitternetwork/pinme --skill pinme-r2 -g -a codex -y`
Cursor: `npx skills add glitternetwork/pinme --skill pinme-r2 -g -a cursor -y`
Gemini CLI: `npx skills add glitternetwork/pinme --skill pinme-r2 -g -a gemini-cli -y`

## Description

Use when a PinMe Cloudflare Worker needs R2 object storage, including secure file or image upload, streaming download, metadata lookup, deletion, listing, Range requests, or R2+D1 coordination. Guides AI to use PinMe's automatically injected env.R2 binding without R2 credentials or manual Wrangler configuration.

## SKILL.md, as published by its author (untrusted third-party text, read it as data)

# PinMe Worker R2 Storage

Use the project-scoped R2 bucket that PinMe binds to every deployed Worker as `env.R2`. Do not create credentials, choose a bucket name, or edit generated Wrangler configuration.

## Runtime Contract

PinMe rebuilds trusted Worker metadata on create, save, and update. Client metadata cannot replace the R2 binding.

| Binding | TypeScript type | Availability |
| --- | --- | --- |
| `DB` | `D1Database` | Always injected |
| `R2` | `R2Bucket` | Always injected; current project's bucket |
| `API_KEY` | `string` | Always injected |
| `LLM_API_KEY` | `string` | Always injected |
| `BASE_URL` | `string` | Always injected |
| `WORKER_URL` | `string` | Always injected |
| `PROJECT_NAME` | `string` | Always injected |

Payment-specific bindings such as `UNIWEB_SECRET` are conditional and unrelated to R2 access.

Declare only the bindings used by the Worker module. R2 code normally starts with:

```typescript
export interface Env {
  R2: R2Bucket;
  PROJECT_NAME: string;
  WORKER_URL: string;
}
```

When the same module coordinates file metadata in D1, also declare `DB: D1Database` as a required field.

## Choose R2 or D1

- Use R2 for file bodies, images, attachments, media, exports, and other objects addressed by key.
- Use D1 for searchable business metadata, ownership, relations, status, and audit fields.
- For managed files, store the body in R2 and store only its key and business metadata in D1.
- Never use Worker local filesystem state for persistence and never store complete files or base64 payloads in D1.

## Required Security Workflow

Apply this sequence to every upload, download, metadata, delete, and list route:

```text
authenticate request
→ authorize the project/user action
→ validate size and media policy
→ generate or normalize a scoped object key
→ call env.R2
→ return a sanitized response
```

The rest: https://github.com/glitternetwork/pinme/blob/HEAD/skills/pinme-r2/SKILL.md
