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: the screenshot exists before the PR does #
An agent that just changed your UI has a screenshot and nowhere to put it. There is no pull request to attach it to yet, and GitHub's own hosting only works inside GitHub. 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 #
Then run uploads login and you're set.
Something not working? uploads doctor checks your setup and points at the fix.
Step 2: Teach your agent how to add screenshots #
One command sets up your coding agent:
That installs the agent skills (when to capture as you go, when to annotate, and the full CLI reference) and registers the MCP server so the agent can upload without shelling out. The skills and MCP are also what a browserless agent — CI job, review bot, or one using https://agents.uploads.sh/mcp with no local git — uses to stage and promote.
Hosted put accepts base64 or a public HTTPS contentUrl. Skill vs. MCP → covers which surface fits your runtime.
On another agent runtime? Wire up each piece yourself —see the setup →.
# install the agent skills
npx skills add buildinternet/uploads
# register the hosted MCP server
# Claude Code
claude mcp add --transport http uploads https://agents.uploads.sh/mcp
# Codex
codex mcp add uploads --url https://agents.uploads.sh/mcp
# OpenCode
opencode mcp add uploads --url https://agents.uploads.sh/mcpStep 3: The agent stages screenshots as it works #
No pull request required. On a branch, a bare put stages the file automatically:
$ uploads put ./after.png --state after
# staged for this branch — auto-comments to the PR when it opens
# once the PR exists, run: uploads attach --promoteKeep doing that at each visual milestone. Check the queue with uploads staged. When the PR opens, staged files promote into one managed comment — via the GitHub App, oruploads attach --promote without the App.
uploads screenshot captures and stages the same way. Tag a pair with --state before and --state after and they render side by side.
Why the URLs matter
Keys are hash-free. Upload the same filename again and every embed shows the new image at the same URL within a minute. No stale screenshots.
Already have a PR open? #
attach is the direct path. It finds the PR through gh, uploads each file, and keeps one managed comment:
Off the PR branch, point it somewhere: add --issue <n> or --pr <n>, and --repo owner/name for a different repo. Placing the image yourself in a PR description or README? --no-comment prints the URL and Markdown without posting.
One image on an open PR? gh pr comment --attach does that now too.
Video and GIFs #
A short screen recording is often the best proof that a change works. The same put handles it — MP4, WebM, and GIFs upload as-is and stage on the branch. One caveat: GitHub only plays videos it hosts itself, so 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 #
- Can't my agent just use gh --attach?
- Since September 2026, yes, for images and video on an existing issue or pull request. Uploads is for the rest of the loop: capturing the shot, staging it before the PR opens, one comment that updates on every revision, and a public URL you can paste anywhere.
- What if my agent has no shell or gh?
- Use the hosted MCP server at agents.uploads.sh. Its put tool takes files as base64 or a public URL and posts them to a PR or issue, with no filesystem or gh required. GitHub has no public API (yet) for attachments, so this is the path for agents that cannot run a command.
- 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 GIFs 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 agent skills (stage-as-you-go workflow, CLI reference, and annotations) and registers the hosted MCP server with Claude Code. After that, the agent runs uploads put <file> on the branch as it works. When the PR opens, staged files land in one attachments comment.
- Can I mark up a screenshot before attaching it?
- Yes. uploads screenshot --annotate bakes boxes, arrows, labels, freeform strokes, and redactions into a capture (CSS selectors on a live page). uploads annotate does the same on an existing image with pixel coordinates. See the Attach & share docs and the annotate-screenshots skill.
- 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 — use a solid redaction (uploads annotate / screenshot --annotate) when a capture shows credentials. Create your own workspace (GitHub-linked) or accept an invite from a workspace admin.
Every command and flag is in the docs. Agents can read /llms.txt or the one-file /llms-full.txt. If this saved you a hand-rolled upload script, a star on GitHub helps others find it.