Quick Share is a small CLI-first tool for making shared Cloudflare R2 assets easy to find from any project.
The goal is simple: once a project is configured, agents and developers can run boring commands like quick-share images or quick-share urls from the project root. No remembered bucket URLs, no copied curl snippets, no custom integration work per project.
quick-share initto configure any project in one commandquick-share setup-serviceto prepare the Cloudflare Worker/R2 service with Wranglerquick-share healthto check the hosted Workerquick-share filesto list shared filesquick-share urlsto print public URLsquick-share imagesto print public image URLsquick-share open <file>andquick-share copy <file>for quick use.quick-share.jsonproject config discovered from the current directory or parent folders- Optional browser library for humans
- Read-only Cloudflare Worker API backed by R2
From this repo:
npm linkThen check:
quick-share helpWithout linking, use:
npm run quick-share -- helpIf the hosted Worker does not exist yet, set up the service first:
quick-share setup-service --bucket quick-share-assets --public-url https://YOUR-PUBLIC-BUCKET.r2.devThis checks for Wrangler, installs it locally if needed, checks Cloudflare authentication, creates the R2 bucket, writes wrangler.toml, and deploys the Worker.
If Cloudflare auth is not ready, the CLI will stop and tell you to use one of:
wrangler login
export CLOUDFLARE_API_TOKEN=your_token_hereCloudflare documents R2 public development URLs as a dashboard setting, so if you do not provide --public-url, the Worker can list files but file objects will not include public asset URLs yet.
Configure Hermes, OpenClaw, Codex, Claude project folders, or any other repo:
quick-share init https://YOUR-WORKER.workers.dev hermes/ --project /Users/jack/Documents/GitHub/hermes
quick-share init https://YOUR-WORKER.workers.dev openclaw/ --project /Users/jack/Documents/GitHub/openclawThat writes:
.quick-share.json- a short
AGENTS.mdQuick Share note, if one is not already present
After setup, anyone can use the project naturally:
cd /Users/jack/Documents/GitHub/hermes
quick-share health
quick-share images
quick-share urls
quick-share files handovers/List files using the project default prefix:
quick-share filesList files under another prefix:
quick-share files client-name/Print URLs only:
quick-share urlsPrint image URLs only:
quick-share imagesOpen or copy by exact name, partial name, or list index:
quick-share open logo.png
quick-share copy "hero"
quick-share copy 1Show which config the CLI found:
quick-share wherePreferred:
quick-share setup-service --bucket quick-share-assets --public-url https://YOUR-PUBLIC-BUCKET.r2.devUseful options:
quick-share setup-service --name quick-share-api
quick-share setup-service --bucket client-images
quick-share setup-service --cors-origin https://quick-share-library.pages.dev
quick-share setup-service --no-deploy
quick-share setup-service --skip-bucket-create
quick-share setup-service --no-installManual fallback:
- Copy
wrangler.toml.exampletowrangler.toml. - Edit
bucket_name,PUBLIC_BASE_URL, andCORS_ORIGIN. - Run
wrangler loginor setCLOUDFLARE_API_TOKEN. - Run
wrangler r2 bucket create <bucket>. - Run
wrangler deploy.
Preview locally:
npm run previewDeploy the static browser library:
QUICK_SHARE_WORKER_URL="https://YOUR-WORKER.workers.dev/files" \
QUICK_SHARE_PUBLIC_URL="https://YOUR-PUBLIC-BUCKET.r2.dev" \
./scripts/deploy-library.sh quick-share-libraryThe CLI talks to these read-only endpoints:
GET /healthGET /.well-known/quick-share.jsonGET /filesGET /files?format=ndjsonGET /openapi.json
GET /files returns:
{
"service": "quick-share",
"schemaVersion": "1.0",
"files": [
{
"name": "example.jpg",
"size": 12345,
"uploadedAt": "2026-06-30T12:00:00.000Z",
"etag": "abc123",
"httpEtag": "\"abc123\"",
"mimeType": "image/jpeg",
"url": "https://pub-example.r2.dev/example.jpg"
}
],
"truncated": false,
"cursor": null,
"next": null
}- Quick Share is read-only.
- It lists metadata from R2 at request time.
- Public URLs only work while the bucket/object/domain remains public.
- It is not an auth system.
- Do not expose private client files without adding authentication and signed URLs.
npm run checkRun ./upload-file.sh to choose a file, or ./upload-file.sh "path/to/file.pdf" to upload directly. Cancelling exits without uploading. Uses ~/.r2-config, created by ./setup-r2.sh. Uploads are public; matching filenames are replaced.
The macOS extension in raycast/ adds Upload File and Recent Uploads. Each user supplies their own R2 bucket and credentials in Raycast preferences. It uses rclone, gives each upload a unique public URL, and copies the link. See installation and development. The CLI and Worker API remain read-only.
The deployed library lives in assets/jack-files/ with its Pages configuration in
deploy/jack-files/wrangler.json. The discovery CLI and its read-only Worker remain separate.
- Larger lazy-loaded previews, video durations, readable titles with original filenames, grid/list views, search, folders, type filters, and sorting.
- Select files to copy their public links or download a ZIP. ZIPs are built in a browser worker, with a visible limit of 100 files / 500 MB to bound browser memory use.
- Named collections persist selected R2 keys in
.quickshare/collections/<uuid>.json. Anyone with a collection URL can preview/download it. They reference current objects; they are not immutable copies, private shares, or a separate backup. - Uploads and collection creation require the owner's passphrase. Authentication uses
an HMAC-signed Secure/HttpOnly/SameSite cookie lasting 30 days. Set
UPLOAD_PASSWORDusing Pages secrets; changing it invalidates all sessions. Use a long random passphrase. - Browser uploads use unique
uploads/<uuid>/<filename>keys and the existingFILESR2 binding. They never replace an existing file. Multipart parts are 8 MiB; the app accepts files up to 5 GiB, retries interrupted parts, and supports cancel/retry. The page must remain open; reload does not resume a previous upload. Reload may leave unfinished multipart uploads for bucket lifecycle cleanup; cancel attempts to abort immediately. - Everything uploaded is public. The upload credential never belongs in source code, localStorage, collection links, or the public R2 bucket.
Deploy the library and its Pages Worker together:
CLOUDFLARE_ACCOUNT_ID=1d7541992ccacf0931ee0e385daa5e08 \
CLOUDFLARE_API_TOKEN="$(secret CLOUDFLARE_PAGES_TOKEN)" npm run deploy:jack-filesSet the upload passphrase through wrangler pages secret put UPLOAD_PASSWORD --project-name=jack-files
from deploy/jack-files/, then deploy. Secrets are configured separately for production
and preview environments. For local development with isolated local R2 storage:
cd deploy/jack-files
wrangler pages dev --r2 FILES --binding UPLOAD_PASSWORD=local-test-passphraseRun npm test and npm run check. The tests cover public discovery, authentication,
origin validation, multipart completion/abort, persistent collections, attachment headers,
unsafe inline content and ZIP boundaries. The live site also needs browser checks for
playback, real upload progress, ZIP downloads and mobile layout.