CLI file sharing and link shortening with download tracking. Backed by Cloudflare R2 + Workers KV + Workers. Zero cost, full ownership.
Live at icecube.to ยท ๐ง.to
Google Drive has no CLI. transfer.sh is dead. Presigned S3 URLs expire. This uploads a file or shortens a URL, gives you a short link, copies it to clipboard. Done.
$ share upload README.md --slug readme.md --public
https://icecube.to/readme.md (copied)
$ share link https://github.com/adriangalilea/share --slug gh --public
https://icecube.to/gh โ https://github.com/adriangalilea/share (copied)
$ share ls
Files
โโโโโโโโโโโโโณโโโโโโโโโโโโณโโโโโโโโโโโณโโโโโโโโโโโโโณโโโโโโณโโโโโโ
โ Slug โ Name โ Size โ Uploaded โ DLs โ Vis โ
โกโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฉ
โ readme.md โ README.md โ 7.2 KB โ 2026-03-19 โ 15 โ pub โ
โโโโโโโโโโโโโดโโโโโโโโโโโโดโโโโโโโโโโโดโโโโโโโโโโโโโดโโโโโโดโโโโโโ
Links
โโโโโโโโณโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโณโโโโโโโโโโโโโณโโโโโโโโโณโโโโโโ
โ Slug โ URL โ Created โ Clicks โ Vis โ
โกโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฉ
โ gh โ https://github.com/adriangalilea/share โ 2026-03-19 โ 2 โ pub โ
โโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโดโโโโโโโโโดโโโโโโ
icecube.to/<slug>
$ share rm gh
Deleted https://github.com/adriangalilea/share (/gh)
This README is shared at icecube.to/readme.md.
share upload <file> # upload file, auto-generate slug
share upload <file> --slug <name> # custom slug
share upload <file> --public # show on landing page (default: private)
share upload <file> --name <name> # override download filename
share upload <file> --keep-metadata # skip EXIF/metadata stripping
share link <url> # shorten a URL
share link <url> --slug <name> # custom slug for short link
share link <url> --public # show on landing page
share ls # list all files and links
share rm <slug> # delete by slug, filename, URL, or r2_key
share setup # interactive first-time configUploads strip EXIF/metadata by default (images via Pillow, videos via ffmpeg).
uv tool install git+https://github.com/adriangalilea/share.gitCLI (Python) Cloudflare Free Tier
โโโโโโโโโโโโโโโโ boto3/S3 API โโโโโโโโโโโโโโโโโโโ
โ share CLI โ โโโโโโโโโโโโโโโโโโ โ R2 โ files (10GB free)
โ โ โโโโโโโโโโฌโโโโโโโโโ
โ โ CF Python SDK โ
โ โ โโโโโโโโโโโโโโโโโโ โโโโโโโโโโดโโโโโโโโโ
โ โ โ KV โ slug โ metadata
โโโโโโโโโโโโโโโโ โโโโโโโโโโฌโโโโโโโโโ
โ
Browser โ
โโโโโโโโโโโโโโโโ โโโโโโโโโโดโโโโโโโโโ
โ short link โ โโโโโโโโโโโโโโโโโโ โ Worker โ serves files,
โ โ โ (custom domain) โ tracks downloads,
โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ landing page
The CLI uploads files to R2 and writes metadata to KV keyed by slug:<slug>. The Worker on your custom domain looks up slugs, streams files from R2 with range request support (for video/audio streaming), and increments download counters.
Every response carries a Content-Disposition header with the original filename so downloads keep their extension regardless of browser or OS (the slug in the URL has no extension; without this header some browsers save the file extensionless). Previewable types โ text/*, anything containing json/xml/javascript, image/*, audio/*, video/*, and application/pdf โ are served inline so the link still renders in-tab. Everything else (all archives: .7z, .zip, .tar, .gz, .rar, โฆ; binaries; unknown application/octet-stream) is served attachment and downloads with the correct name.
- Python >=3.12, uv
- Cloudflare account (free tier)
- Node.js (for worker deployment)
- A domain pointed to Cloudflare nameservers
uv tool install git+https://github.com/adriangalilea/share.gitYou need two API tokens:
R2 API token (S3-compatible, for file uploads):
- Cloudflare dashboard โ R2 โ Manage R2 API Tokens โ Create
- Permissions: Object Read & Write
- Save the Access Key ID + Secret
CF API token (for KV + worker deployment):
- My Profile โ API Tokens โ Create Token
- Use template: Edit Cloudflare Workers
- Add permissions: Zone DNS Edit + Zone Read
- Save the token
share setupThis verifies credentials, creates the R2 bucket and KV namespace, and writes config to ~/.config/share/config.toml.
Clone the repo and edit worker/wrangler.toml:
name = "share"
main = "src/index.ts"
compatibility_date = "2026-03-19"
[[r2_buckets]]
binding = "R2"
bucket_name = "share"
[[kv_namespaces]]
binding = "KV"
id = "your-kv-namespace-id" # printed by share setup
[[routes]]
pattern = "yourdomain.com"
custom_domain = true
[vars]
SITE_NAME = "yourdomain.com"Then deploy:
cd worker
npx wrangler deployIf not already done:
- Cloudflare dashboard โ Add a site โ your domain
- Update nameservers at your registrar to the ones Cloudflare gives you
- The worker deploy will create the DNS records automatically
- SSL/TLS โ Edge Certificates โ Always Use HTTPS โ ON
share upload myfile.pdf
# https://yourdomain.com/kX9mT (copied)~/.config/share/config.toml โ see config.example.toml.
| Key | Description |
|---|---|
cloudflare.account_id |
Cloudflare account ID |
cloudflare.r2_access_key_id |
R2 S3 API access key |
cloudflare.r2_secret_access_key |
R2 S3 API secret key |
cloudflare.api_token |
CF API token |
cloudflare.bucket |
R2 bucket name (default: share) |
cloudflare.kv_namespace_id |
Workers KV namespace ID |
urls.public_base |
Your domain (e.g. https://yourdomain.com) |
upload.strip_metadata |
Strip EXIF before upload (default: true) |
| Service | Limit | Usage |
|---|---|---|
| R2 | 10 GB storage, 1M writes/mo, 10M reads/mo, zero egress | File storage |
| Workers KV | 1 GB storage, 100K reads/day, 1K writes/day | File metadata |
| Workers | 100K requests/day, 10ms CPU/request | Serve files + landing page |
R2's S3 endpoint uses TLS that some VPNs break. If uploads fail with SSL errors, bypass VPN for r2.cloudflarestorage.com.
slug:<slug> โ file: { type?, name, size, content_type, uploaded_at, downloads, r2_key, slug, public }
slug:<slug> โ link: { type: "link", url, slug, created_at, clicks, public }