@kentcdodds/agent-files
Mint short-lived R2 PUT URLs for agent file handoffs; public download via managed r2.dev.
README.md
75 lines · 3.3 KB · Markdown@kentcdodds/agent-files
Intent
Move file bytes between an agent's own machine (Cursor cloud agent VM, local
shell, another process) and Kody runtimes — in either direction — without
shoving multi‑MB payloads through MCP base64 or Dropbox. Mint a short‑lived R2
PUT URL with a small MCP/execute call, PUT the bytes with curl/fetch from
the machine that has them, then read the public managed *.r2.dev downloadUrl
from Kody (or hand it to another agent). Objects live in the agent-files
bucket on Kent's Cloudflare account and expire after about a week.
When to use
- A cloud agent VM (or any host without Cloudflare credentials) needs to stage bytes that Kody will later fetch or copy into another R2 bucket.
- Kody needs to publish a download URL that a machine without secrets can GET.
- Agent-to-agent handoffs of images, archives, logs, or other binaries.
Prefer this over MCP bytesBase64 for anything beyond a few hundred KB.
Prerequisites
- User secret
cloudflareApiToken(same token used by home-maintenance / stash) with permission to manage R2 on Cloudflare accounta41d50ecaf0ae0f86dd1824ef6729cb2. - Token must be able to call
https://api.cloudflare.com(R2 bucket create, managed public domain, temp-access-credentials).
Create or rotate the token in the Cloudflare dashboard: API Tokens. Prefer a custom token with Account → Cloudflare R2 → Edit (and Tokens → Read for parent key id resolution).
Setup
- Ensure
cloudflareApiTokenexists as a user secret in Kody (name only — never paste the value into chat or commits). - First successful
create-upload/uploadauto-ensures:- R2 bucket
agent-fileson accounta41d50ecaf0ae0f86dd1824ef6729cb2 - Managed public
*.r2.devdomain - Object lifecycle delete after ~7 days (best-effort; see below if it fails)
- R2 bucket
- No package-local secrets beyond the mounted user token.
Manual lifecycle (if auto-apply fails)
Dashboard → R2 → bucket agent-files → Settings → Object lifecycle → add a
rule that deletes objects after 7 days (empty prefix = whole bucket).
How it works
- Call
./create-uploadwith{ filename, confirm: true }(optionalcontentType,prefix,expiresInSeconds). - PUT file bytes to
upload.urlwith the returnedupload.headers(Content-Typemust match) — typically from the VM/machine that has the file. - From Kody
execute(or another package),fetch(downloadUrl)to read the bytes, or passdownloadUrlinto something like@kentcdodds/cloudflare/r2-put-objectto copy into a durable R2 bucket. - Optionally
./get/./deletebykey.
Handoffs are short-lived: upload URL TTL ~1h (default); objects ~7 day lifecycle.
Prefer ./create-upload over ./upload. The latter accepts small
bytesBase64 payloads only and rejects oversized MCP bodies.
Done when
create-uploadwithconfirm: truereturnsupload.url+downloadUrl- A real PUT to
upload.urlsucceeds - GET
downloadUrlreturns 200 with the bytes ./get({ key })reportsfound: true./delete({ key, confirm: true })removes the object
Bucket / public URL base are created on first use; check the first
create-upload result's downloadUrl host (e.g. https://pub-….r2.dev/…).