Docs
Put screenshots and other media on GitHub — PRs, issues, code reviews — with one command.
What it does #
Getting an image into a GitHub comment is easy for a person — you drag it in. For an agent or a script, there is no drag-and-drop. uploads.sh fills that gap: it hosts your file at a stable public URL and posts it to the right place on GitHub for you.
The everyday flow is two commands:
>> uploading ./before.png >> optimized 421337 → 96412 bytes (before.webp) >> uploading ./after.png >> optimized 407190 → 91205 bytes (after.webp) URL: https://storage.uploads.sh/gh/you/app/pull/123/before.webp MARKDOWN:  URL: https://storage.uploads.sh/gh/you/app/pull/123/after.webp MARKDOWN:  >> attachments comment updated
That's it. The CLI figures out which repo and pull request you're on, uploads the files, and keeps one tidy "📎 Attachments" comment on the PR up to date.
Setting up a coding agent to do this end to end? There's a dedicated walkthrough: how to get agents to upload screenshots & video to GitHub.
Install & sign in #
Install the CLI globally, then sign in once:
uploads login opens a browser so you can approve the sign-in (GitHub or a magic link). Access is by invitation — an uploads.sh administrator invites your email to a workspace first. Once approved, the CLI mints a workspace token and saves it, so you only do this once per machine.
Prefer not to install anything? Every command works as a one-off with npx:
To check that everything is wired up:
Attach files to a PR #
attach is the command you'll use most. From a checked-out branch with an open pull request, it needs no arguments beyond the files:
…which lands on the pull request as one managed comment:
📎 Attachments
Run attach again with new files and this same comment updates in place — your PR doesn't collect a trail of stale screenshot comments.
It uses the gh CLI to find the current repo and PR. If you're not on a PR branch — or you want a different target — say so explicitly:
Want the URLs and ready-to-paste Markdown without touching any GitHub comment — say, to drop an image into a PR description yourself?
Get a URL for any file #
put is the simpler building block: upload one file, get back a public URL and Markdown you can paste anywhere.
>> uploading ./shot.png
>> optimized 421337 → 96412 bytes (shot.webp)
>> key: screenshots/app/2026-07-12/shot-9f2c1a.webp
URL: https://storage.uploads.sh/screenshots/app/2026-07-12/shot-9f2c1a.webp
MARKDOWN: A few useful variations:
By default, images are re-encoded to WebP (capped size, high quality) so GitHub embeds stay fast, and EXIF metadata is stripped. Use --keep-exif to keep metadata, or --no-optimize to skip all processing.
Set up your agent #
If you use Claude Code or another agent runtime, one command installs both the agent skill and the hosted MCP server:
Or set up each piece yourself:
The skill teaches the agent when and how to use the CLI — for example, attaching before/after screenshots to the PR it just opened. The MCP server gives agents the same tools (put, attach, list, delete, and more) over HTTP, using the same token as the CLI. There's also a local stdio variant if you prefer:
Manage what you uploaded #
Good to know #
- Hosted files are public. Anyone with the URL can view them — even media attached to private repositories. Don't upload secrets or sensitive UI.
- Access is by invitation. There's no self-serve signup right now. If you'd like in, reach out via the GitHub repo.
- Everything lands in your workspace. Files are stored under a prefix for your workspace, and PR/issue attachments get stable, predictable paths — so re-attaching an updated screenshot replaces the old URL's spot instead of littering.
- Still early. uploads.sh is built in the open and APIs may change without notice. Don't depend on it for anything you can't afford to re-key.