Skip to main content

CLI file sharing and link shortening. Backed by Cloudflare R2 + Workers.

Project description

share

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

Why

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.

Usage

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 config

Uploads strip EXIF/metadata by default (images via Pillow, videos via ffmpeg).

Install

uv tool install git+https://github.com/adriangalilea/share.git

Architecture

CLI (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.

Self-hosting

Prerequisites

  • Python >=3.12, uv
  • Cloudflare account (free tier)
  • Node.js (for worker deployment)
  • A domain pointed to Cloudflare nameservers

1. Install the CLI

uv tool install git+https://github.com/adriangalilea/share.git

2. Create Cloudflare resources

You 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

3. Run setup

share setup

This verifies credentials, creates the R2 bucket and KV namespace, and writes config to ~/.config/share/config.toml.

4. Configure and deploy the worker

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 deploy

5. Add your domain to Cloudflare

If not already done:

  1. Cloudflare dashboard โ†’ Add a site โ†’ your domain
  2. Update nameservers at your registrar to the ones Cloudflare gives you
  3. The worker deploy will create the DNS records automatically
  4. SSL/TLS โ†’ Edge Certificates โ†’ Always Use HTTPS โ†’ ON

6. Upload

share upload myfile.pdf
# https://yourdomain.com/kX9mT (copied)

Config

~/.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)

Cloudflare free tier limits

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

VPN note

R2's S3 endpoint uses TLS that some VPNs break. If uploads fail with SSL errors, bypass VPN for r2.cloudflarestorage.com.

KV schema

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 }

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

share-0.5.1.tar.gz (14.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

share-0.5.1-py3-none-any.whl (9.0 kB view details)

Uploaded Python 3

File details

Details for the file share-0.5.1.tar.gz.

File metadata

  • Download URL: share-0.5.1.tar.gz
  • Upload date:
  • Size: 14.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for share-0.5.1.tar.gz
Algorithm Hash digest
SHA256 f4ecdecf51cb2b1b4fae50eabc29ab77c616f1bf695043acbc06ffa815ffe8bf
MD5 81d870499ef76522279fe47847e9f3ab
BLAKE2b-256 a76c803b2198edbe7051509d15814c829959904cbe9fc59ed1e4560536f95f5f

See more details on using hashes here.

Provenance

The following attestation bundles were made for share-0.5.1.tar.gz:

Publisher: release.yml on adriangalilea/share

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file share-0.5.1-py3-none-any.whl.

File metadata

  • Download URL: share-0.5.1-py3-none-any.whl
  • Upload date:
  • Size: 9.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for share-0.5.1-py3-none-any.whl
Algorithm Hash digest
SHA256 19783caf238c4c8db2f884094fa215cda941214597b2fb1b5b41cf4c82ee19c1
MD5 963ab218472bbec1bd39c02145f82790
BLAKE2b-256 ce31cce9178f05bd54483e3bc8303514932eb5be11358719d0819cf0f463c02b

See more details on using hashes here.

Provenance

The following attestation bundles were made for share-0.5.1-py3-none-any.whl:

Publisher: release.yml on adriangalilea/share

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page