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 #
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 on agents.uploads.sh 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 mcp add --transport http uploads 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.
Video and everything else #
A short screen recording is often the best proof that a change works. The same put handles it — MP4, WebM, GIFs, zips, and logs all 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 #
- 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 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.