Agent walkthrough

How to get agents to upload screenshots & video to GitHub

Claude Code, CI jobs, review bots, plain scripts: anything without a browser.

The problem: no drag-and-drop from a terminal #

You put a screenshot on a pull request by dragging the file into the comment box. GitHub then hosts it at github.com/user-attachments/…. That only works in a signed-in browser. There is no gh command and no API for it.

So an agent that just changed your UI can't show its work. The usual workarounds all hurt:

  • Committing images to the repo bloats it forever, for a screenshot that matters once.
  • Random image hosts give you random URLs, expiring links, or need a browser anyway.
  • A hand-rolled S3 script works fine until you want stable URLs, image optimization, and comment cleanup.

The fix: host the file at a public URL the agent can create itself, then write plain Markdown. That's what uploads.sh does.

Step 1: install the CLI and sign in (once) #

npm install -g @buildinternet/uploads
uploads login

uploads login trades an invite code for a workspace token and saves it. You do this once per machine. Access is invite-only for now; ask via the GitHub repo. Check your setup with uploads doctor.

Step 2: teach your agent #

One command sets up Claude Code:

uploads install
  • The agent skill teaches the agent when to attach screenshots, like before/after shots on a PR it just opened.
  • The MCP server offers the same tools (put, attach, list, delete, …) for runtimes that prefer MCP.

Or set up each piece yourself, for other agent runtimes:

npx skills add buildinternet/uploads --skill uploads-cli
claude mcp add --transport http uploads https://agents.uploads.sh/mcp

Step 3: the agent attaches media with one command #

From a branch with an open pull request, attach only needs the files. It finds the PR through gh, uploads each file to a stable URL, and keeps one managed comment:

uploads attach ./before.png ./after.png
# optimizes each image, then keeps one comment on the PR up to date
>> uploading ./before.png
>> uploading ./after.png
>> attachments comment updated

Not on a PR branch? Point it somewhere:

uploads attach ./repro.gif --issue 45
uploads attach ./shot.png --repo owner/name --pr 123

Want to place the image yourself, in a PR description or README? --no-comment prints the URL and Markdown without posting anything. uploads put gives full control over naming and output.

Why the URLs matter

Attachments get stable keys, like gh/owner/repo/pull/123/shot.webp. Upload the same filename again and the PR shows the new image at the same URL within a minute. No stale screenshots.

Video and everything else #

A short screen recording is often the best proof that a change works. MP4, WebM, GIFs, zips, logs all upload as-is:

uploads attach ./demo.mp4 # linked from the comment

One caveat: GitHub only plays videos it hosts itself. Outside video shows up as a link, not a player. GIFs embed like images.

Images are optimized by default: re-encoded to WebP, size capped, and EXIF stripped so they load fast and leak nothing. Opt out with --no-optimize or --keep-exif. Add device chrome with --frame phone|browser|iphone-16-pro.

FAQ #

Why can't my agent upload images to GitHub directly?
GitHub's own image hosting (github.com/user-attachments) only works when you drag a file into the comment box in a signed-in browser. There is no gh command or API for it. So any image an agent puts in a comment must already live at a public URL.
Do the image URLs change when I re-upload a screenshot?
No. PR and issue attachments get stable keys like gh/owner/repo/pull/123/shot.webp. Upload the same filename again and every embed shows the new image within about a minute.
Can agents upload video to GitHub pull requests?
Yes. MP4, WebM, and other files upload as-is and get a stable public URL. GitHub only plays videos it hosts itself, so the comment links the file instead of embedding a player.
How do I set up Claude Code to attach screenshots to its pull requests?
Run `uploads install` once. It installs the uploads-cli agent skill and registers the hosted MCP server with Claude Code. After that, the agent runs `uploads attach <files>` on its own when it changes something visual.
Are uploaded files private?
No. Files are public to anyone with the URL, even media attached to private repos. Don't upload secrets or sensitive UI. Uploading itself requires an invite-issued workspace token.

Every command and flag is in the docs. Agents can read /llms.txt. If this saved you a hand-rolled upload script, a star on GitHub helps others find it.