Agents can put screenshots on pull requests now, too.
A lightweight file-hosting service on Cloudflare Workers. One command —
uploads attach — hosts a file at a stable public URL and keeps one tidy
attachments comment on the PR. Built on files-sdk so
the storage layer is provider-agnostic (R2 today; any files-sdk adapter later).
uploads.sh · Docs · npm → · Use it · What's in this repo · Develop
Active development — not production-ready. uploads.sh is being built in the open and its APIs (including auth) will change without notice. Don't rely on it for anything you can't afford to lose or re-key.
You add a screenshot to GitHub by dragging it into the comment box. Agents can't — GitHub's native image hosting only works through a browser session, so an agent that just captured a before/after has nowhere to put it.
uploads gives agents that missing step: a CLI and REST API that host files
at stable, public URLs and return ready-to-paste Markdown. --pr/--issue
keys are hash-free, so re-uploading the same filename overwrites in place and
the URL never changes, and a managed attachments comment keeps every file for
a PR in one tidy place. Workspaces keep tenants (and their budgets and key
policies) apart.
This repo is the source of the canonical deployment at
uploads.sh: the API worker, auth worker, MCP server, the
Astro web app, and the @buildinternet/uploads CLI (published to npm from
packages/uploads).
Install the CLI, sign in once, then attach media from a checked-out PR branch:
npm install --global @buildinternet/uploads
uploads login
uploads attach ./before.png ./after.pngFor a one-off run without a global install:
npx @buildinternet/uploads login
npx @buildinternet/uploads attach ./before.png ./after.pngattach detects the GitHub repository and current PR through gh, uploads
all files, and creates or updates one managed attachments comment.
An uploads.sh administrator invites your email to a workspace; uploads login
opens a browser to sign in (GitHub or a magic link) and saves the resulting
workspace token — see enrollment. Hosted files are
public, including media attached to private repositories. Do not upload
secrets or sensitive UI.
Agent skill — an auto-triggering playbook for the CLI, installable into any agent runtime without checking out anything:
npx skills add buildinternet/uploads --skill uploads-cliFull CLI usage — key conventions, stable PR/issue attachments, managed comments, and public galleries — lives in docs/cli.md. REST routes are in docs/api.md.
| Path | What |
|---|---|
apps/api/ |
Hono worker — REST API, deploys to api.uploads.sh |
apps/auth/ |
Better Auth worker — sessions, enrollment, device flow |
apps/mcp/ |
Remote MCP server |
apps/web/ |
Astro site — uploads.sh, account and admin UI |
packages/storage/ |
@uploads/storage — files-sdk adapter factory |
packages/uploads/ |
@buildinternet/uploads — CLI + client, publishes to npm |
packages/ui/ |
@uploads/ui — shared design system |
skills/uploads-cli/ |
Agent skill for driving the CLI |
The workers and web app are separate deployables. All storage access goes
through createStorage() in packages/storage — adding a provider is one new
case plus peer deps, no API changes.
| Doc | Contents |
|---|---|
| cli | CLI usage, GitHub embeds, keys, galleries |
| api | REST routes |
| local-dev | Manual setup, dev stack, smoke tests |
| workspaces | Multi-tenant model, budgets, key policy, BYO-bucket |
| enrollment | Agent login, scopes, expiry, and migration |
| admin-tokens | Minting, listing, and revoking upload tokens |
| ops | Operator runbook (limits, retention, secrets) |
| deploy | Cloudflare setup and production deploy |
| contract testing | Deployed smoke checks and release gate |
| roadmap | Planned features |
Agent and contributor conventions live in AGENTS.md.
Prerequisites: Node ≥24 and pnpm ≥11 (corepack enable). No Cloudflare
account needed for the core local loop — wrangler dev simulates R2, KV, and
D1 on disk:
pnpm bootstrap # one-command setup: tooling, deps, env vars, local D1, default workspace
pnpm doctor # diagnose the setup — reports what's missing and how to fix it
pnpm dev # API on :8787 (local R2 + KV + D1)
pnpm dev:stack # authenticated Auth + API + Web stack at 127.0.0.1:4321
pnpm check # lint + format (the CI gate)
pnpm typecheck # wrangler types + tsc across workspacesbootstrap is idempotent (safe to re-run; never overwrites your env files or
re-mints an existing local workspace) and doctor is read-only. Manual setup
steps, the full dev-stack detail, and a curl smoke test live in
docs/local-dev.md.
MIT.