uploads.sh

sh.uploadsPublished by uploads.shOfficial publisherv0.62.1Updated Nov 5, 2026

Host files from coding agents; stage on a branch and attach to GitHub PRs.

VerifiedStreamable HTTPWeb executableProductivity & WorkflowFiles & StorageDeveloper Tools

Overview

AI-generated overview

uploads.sh hosts agent-produced files at stable public URLs, stages them on a branch and syncs them into one managed GitHub PR or issue comment.

What you can do
  • Upload files, screenshots and local HTML captures, returning public URLs and GitHub-ready markdown
  • Stage files for a branch, list or unstage them, and attach them to a PR or issue with a managed comment
  • Create, read and link public galleries and newest-first screenshot feeds, including repo- or PR-scoped feeds
  • List, search and tag uploaded files by metadata, and read workspace storage usage
  • Delete files, approve uploads held for review, purge expired objects and reconcile usage
  • Check identity and configuration, search product docs, read the changelog and send a diagnostic report
When to use it
Useful when a coding agent needs to publish screenshots, recordings, logs, reports or archives from the terminal and have them appear in a pull request or issue comment, or when an agent that cannot run commands needs to upload files by bytes or URL.
Requirements
Remote endpoint at agents.uploads.sh over streamable HTTP, or the local npm package run as a stdio server. Authentication is required: OAuth in the browser, or a workspace bearer token supplied as UPLOADS_TOKEN or an Authorization header. Optional UPLOADS_API_URL and UPLOADS_WORKSPACE. Local screenshot capture via Chrome needs Chrome installed.
Before you install
Uploaded files are public to anyone holding the URL, including private-repo attachments with non-guessable links. A classifier holds files that look like credentials or personal data, but do not rely on it. Tools can permanently delete files, purge expired objects and post or edit a GitHub comment. The report tool sends a message and optional log to the uploads team, so it should only be used on request and without secrets.

Installation

In SourceWeft

  1. Open uploads.sh in the dashboard and add it to a workspace.
  2. Connect the required credentials. They are stored privately and never shown on public pages.
  3. Enable the server for the chats that should use its tools.

Web executable via Streamable HTTP. Remote servers run from the web runtime once configured in a workspace.

Use with an agent

Paste this prompt into Claude Code, Codex, Cursor or another agent — or into SourceWeft chat. The agent reads this server's install guide, shows you its publisher, endpoint and sign-in, and adds it to your client once you agree. Keys never go into a command.

Read https://sourceweft.com/mcp/sh.uploads%2Fmcp/install.md and connect the MCP server it describes to my client. Before changing any config, show me its publisher, endpoint and sign-in method and wait for my OK. Never put an API key in a command or in a file I would commit; ask me where it should come from.

Read the install guide the agent follows

Other MCP clients

Add this to your client's mcpServers config. The client completes OAuth sign-in on first connect.

{
  "mcpServers": {
    "uploads-sh": {
      "type": "http",
      "url": "https://agents.uploads.sh/mcp"
    }
  }
}

README

[uploads.sh — the missing upload command for coding agents]

uploads

The missing upload command for coding agents.

Capture screenshots, recordings, and other artifacts as you work: test reports, logs, JSON, PDFs, zips. When the pull request opens, uploads.sh puts them in one tidy comment that updates automatically on each revision. Hosted uploads.sh is free to start. Connect your own bucket — Cloudflare R2 or any S3-compatible provider — so storage in that bucket is unmetered, or self-host the open-source service.

uploads.sh  ·  Docs  ·  npm →  ·  Quick start  ·  What it looks like  ·  Screenshots in CI  ·  What's in this repo  ·  Develop

[skills.sh] [CI] [npm (CLI)] [MCP server] [GitHub App: uploads-sh] [Ask DeepWiki] [License: Apache 2.0]

Under active development. uploads.sh is being built in the open, so APIs can still change. Feedback is welcome — open an issue.


Artifacts ready when the pull request opens

uploads hosts the artifacts coding agents produce at stable public URLs they can use in pull requests and issues: screenshots and screen recordings, but also test reports, logs, JSON, CSV, Markdown, PDFs, and zip archives (the full list is under Plans & limits). On a branch, uploads put stages each file as soon as it is ready. When the pull request opens, uploads.sh promotes the staged files into one managed comment.

GitHub's own attachments work from a browser and, since GitHub CLI 2.99 (September 2026), from gh … --attach, but only once a pull request or issue exists, and the files stay behind GitHub's own hosting, where they cannot be embedded or fetched anywhere else. uploads.sh gives agents a stable public URL from the same terminal where they build and test the change, while the branch is still in progress; GitHub has no public API (yet) for that. The hosted MCP server does the same for agents that cannot run a command at all, taking files as bytes or a URL.

Keys are hash-free, so re-uploading the same filename overwrites in place and the URL never changes — every embed of it updates at once. 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 hosted read-gate Worker, the Astro web app, and the @buildinternet/uploads CLI (published to npm from packages/uploads).

What it looks like

One comment per PR, rewritten in place on every sync. Files tagged --state before and --state after pair into a side-by-side table; other images and video land below it, and non-media files (reports, logs, archives) list in a file table with their type and size.

The real comment on #436.

Pairing is by --meta path=… when several pairs share a comment (one before and one after per path), and falls back to filenames that differ only by a before/after token — hero-before.webp with hero-after.webp.

Everything you attach also lands in your workspace, grouped by where it came from — pages by path, projects by repo or app — and browsable from one place.

The screenshots view groups uploads by project and path.

Open any file for a share page: copy-ready embeds (Markdown, HTML, and more), the raw URL, and a delete button.

Each file's share page — copy-ready embeds, details, and delete.

Quick start

Install the CLI and sign in once:

bash
npm install --global @buildinternet/uploadsuploads login

Upload a file and tag the page it shows:

bash
uploads put ./settings.png --meta path=/settings

On a branch, put stages the file automatically. Open the pull request however you normally would. The GitHub App promotes the staged files into one managed attachments comment.

More ways to upload

Use the same commands for before-and-after evidence, an open pull request, a browser capture, or an annotated image:

bash
# Pair two states from the same page in the pull request comment.uploads put ./before.png --meta path=/settings --state beforeuploads put ./after.png --meta path=/settings --state after
# See what this branch will attach when the pull request opens.uploads staged
# Attach files directly when a pull request or issue is already open.uploads attach ./before.png ./after.png
# Capture, annotate, and upload a page in one command.uploads screenshot http://localhost:4321/settings --via local --annotate ./callouts.json

attach detects the repository and current PR through gh, uploads all files, and creates or updates that same one comment. On an issue it also keeps a Markdown issue artifact (and a gallery link, when there is one) unless the workspace or the repo turns that off. Without the GitHub App, run uploads attach --promote after opening the pull request to promote files that you staged earlier. All commands run under npx @buildinternet/uploads … without a global install.

Sign in with GitHub or a magic link, then create your own workspace or accept an invite into one — see enrollment. Hosted files are public URLs — private-repo attachments get non-guessable links (how that works), but anyone holding a URL can view the file. A file that looks like it shows a credential, ID, or card number is held for your review before it goes public, but don't rely on that: do not upload secrets or sensitive UI.

Require screenshots in CI

The GitHub App adds an uploads.sh check to pull requests that change UI files, next to your tests and builds. No workflow or Actions step is needed. Out of the box it only reports, so nobody is blocked. Turn on Require screenshots on UI changes in the workspace's Settings → GitHub, or set it for one repo in .uploads.yml, and the check fails until screenshots arrive:

yaml
comment:  check:    require: [before-after, desktop, mobile] # or just [uploads]

The PR comment shows a checklist that ticks itself as files arrive. Images dragged into the PR on GitHub count too, so contributors without uploads.sh are never stuck, and a skip-uploads label skips a PR that needs no screenshots. Add uploads.sh as a required status check in branch protection to make it block merges. Setup, which files count as UI, and skip labels are in Require screenshots on pull requests.

Connect your agent

The hosted MCP server runs at https://agents.uploads.sh/mcp and is listed in the MCP Registry as sh.uploads/mcp. Local stdio is uploads mcp on the same npm package.

bash
# Claude Codeclaude mcp add --transport http uploads https://agents.uploads.sh/mcp
# Codexcodex mcp add uploads --url https://agents.uploads.sh/mcp
# OpenCodeopencode mcp add uploads --url https://agents.uploads.sh/mcp

uploads install adds the agent skills and the MCP server, so future sessions can capture each visual milestone without being asked. The skills also install standalone into any agent runtime:

bash
npx skills add buildinternet/uploads

That installs three skills: github-screenshots (visuals → PRs/issues), uploads-cli (full CLI reference), and annotate-screenshots (callouts and redaction on a capture).

On Claude Code or Codex, the plugin bundles the skills, the MCP server, and a pre-PR screenshot reminder. In Claude Code it also shows staged screenshots above the prompt and attaches them when the PR opens. On claude.ai and in Cowork, add uploads from the Claude directory. The same folder (plugins/claude/uploads) is the common agent-plugin layout, and it is submitted to the xAI plugin marketplace as uploads.

Full CLI usage, including annotations, managed comments, public galleries, and change feeds (repo-wide or one pull request), lives in docs/cli.md.

uploads feed create prints a live page of the screenshots on a repo:

uploads feed create --repo buildinternet/uploads.

REST routes are in docs/api.md.

What's in this repo

PathWhat
apps/The deployables: the REST API worker (api.uploads.sh), the optional public viewer, the auth worker, the remote MCP server, the Slack app (link previews and held-upload messages), the hosted read-gate Worker, and the Astro site at uploads.sh
packages/Shared code — most notably @buildinternet/uploads (the CLI, published to npm), @uploads/storage (the files-sdk adapter factory all storage goes through), and @uploads/plugin (Claude/Codex plugin version, not published)
skills/The three agent skills that ship to users
hooks/, plugins/, .mcp.jsonAgent-runtime wiring: the shared pre-PR screenshot hook and the Claude / Codex plugin manifests
server.jsonMCP Registry listing (sh.uploads/mcp): stdio uploads mcp plus the hosted remote

Each worker and the web app deploy separately. All storage access goes through createStorage() in packages/storage — adding a provider is one new case plus peer deps, no API changes.

Hosted file bytes stay on the shared uploads-default bucket. store.uploads.sh, storage.uploads.sh, and embed.uploads.sh are served through uploads-read-gate (apps/read-gate). A held image gets a "Held for review" card. Any other safety hold is a 404. Every other request passes through to R2. It does not gate private files, and it does not run for a bring-your-own bucket. Operator notes are in docs/ops.md.

Docs

Product docs — install, the staged loop, the GitHub App, limits — live at https://uploads.sh/docs. The docs in this repo are the companion: CLI and API reference, contributor setup, and operator material, all mapped from docs/README.md.

How to set up, test, and open a pull request: CONTRIBUTING.md. Where the project is headed: VISION.md. Agent working conventions live in AGENTS.md, and agents that land on this repo should start at llms.txt. The product site serves https://uploads.sh/llms.txt and https://uploads.sh/llms-full.txt.

Local development

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:

bash
pnpm bootstrap        # one-command setup: tooling, deps, env vars, local D1, default workspacepnpm dev              # API on :8787 (local R2 + KV + D1)

bootstrap is idempotent, and pnpm doctor diagnoses a setup without changing it. The rest of the loop — the authenticated dev stack, the check and test gates, and how to open a pull request — is in CONTRIBUTING.md.

License

Apache 2.0.

Source: README.md at commit 4663b60

Tools

29

feed_create

Create change feed

Create a public newest-first screenshot feed (same product as CLI `uploads feed create`). Pass `repo` alone for the whole GitHub repo. Pass `pr` plus `repo` — or `github` as owner/repo#123 / a GitHub PR URL — to scope that same feed to one pull request. `issue` does the same for an issue. Optional `path` filters by page-path metadata. Creating the same scope again returns the existing URL. This is a live query, not a curated gallery. Anyone who knows the URL can view it. See https://uploads.sh/docs/feeds.

Parametersprpathrepoissuegithubworkspace

feed_get

Get change feed

Get a workspace-owned change feed by ID, including its current newest-first screenshots and the canonical public /c/<id> URL. Each item includes pageUrl (`/c/<id>/<item>`) for the pager. The feed may be repo-wide or scoped to one pull request / issue (see `number` and `kind` on the result). Anyone with the URL can view the media.

ParametersfeedIdrequiredworkspace

put

Upload file

Upload one or more files and get a public URL plus GitHub-ready markdown. Prefer `embedUrl` in GitHub markdown. Pass `contentUrl` for a public HTTPS file, or http://localhost on this machine, instead of a local path. With `pr`/`issue`, keys are stable and the managed comment is synced. `holdCheck: pending` means the classifier may still hold the file for review (it decides after the upload); `comment.held` counts files on the PR or issue held for review; see `list_held`. All uploads are public. Accepts images (PNG, JPEG, GIF, WebP, AVIF), video (MP4, WebM, MOV), PDF, zip, gzip, and text (plain, markdown, CSV, JSON). SVG and XML are accepted only on storage lanes verified to serve them sandboxed (see the workspace's storage settings); HTML is rejected.

ParameterspraltappkeyreffilenoPrrepofilesframeissuenoGit+21 more

screenshot

Capture screenshot

Capture a URL or local HTML file and host it. Shares put's attach, comment, and metadata options. `via=local` needs Chrome; `via=remote` renders server-side. localhost URLs are local-only.

ParameterspraltappcdpkeyrefviahidenoPrrepowaitframe+29 more

attach

Attach to GitHub

Upload one or more files as stable PR/issue attachments (in parallel) and maintain a managed GitHub comment. Returns `uploads` and `failures` (one bad file does not abort the batch). Each success has `url`, `embedUrl`, and `markdown` (prefer embedUrl for GitHub). With no pr/issue, targets the current branch PR, and files already staged for that branch are promoted into it (`promotion`/`promoteError`; renamed branches are followed automatically, or name the old branch with fromBranch). Attachments are public and keys are predictable; upload only non-sensitive media. On an issue, a Markdown artifact (and a gallery link, when there is a gallery) stays in sync with the comment unless `issueArtifacts` is false, the repo sets `comment.issueArtifacts: false`, or the workspace turns it off. Images stay on uploads.sh URLs. Pull requests are unchanged. An artifact failure is a warning and does not fail the attach.

ParametersprapprepofilesrequiredframeissuestatescreencaptionframeFitframeUrlkeepExif+10 more

list

List files

List uploaded objects in the workspace, filtered by key prefix or by a PR/issue's attachments. Paginate with cursor, or set all to fetch every page.

Parametersprallrepoissuelimitcursorprefixworkspace

staged

List staged files

List files staged for a git branch and whether they will auto-attach when a PR opens. Returns `{ repo, branch, files, binding }`.

Parametersrepobranchworkspace

unstage

Unstage files

Clear staged files for a branch, or specific keys, without deleting them. Sets gh.status=unstaged so they drop out of uploads staged and auto-promotion. Pass branch (repo inferred) or keys, not both. Needs files:write.

ParameterskeysrepobranchdryRunworkspace

delete

Delete file

Permanently delete one uploaded file by key, along with its metadata. Set dryRun to preview without deleting.

ParameterskeyrequireddryRunworkspace

get_metadata

Get metadata

Read the queryable tags on one file. Returns `{ metadata }` (empty when none). Same as `uploads meta get`.

Parameterskeyrequiredworkspace

list_held

List held files

List uploads held for review. The classifier holds a file it thinks shows a secret (an API key, a password, a token) or sensitive personal data (an ID, a card number). A held file stays out of the managed PR comment, feeds, and galleries until a workspace member approves it with `approve`. A signed-in member sees the real file on its /f/ page. On hosted storage an image URL returns a Held for review card, and any other raw URL returns 404. Pass `pr`/`issue` for one PR or issue, or `prefix`. Each item has a `reason` such as `secret: api_key`, and `sha`, the content hash of those bytes. `approve` sends that hash. Same as `uploads approve --pr <n>`.

Parametersprrepoissueprefixworkspace

approve

Approve held files

Release uploads held for review (see `list_held`): pass `keys`, or `pr`/`issue` to approve every held file there. The file returns at the same URL and the managed PR comment re-syncs. Check the file first: if it shows a real credential, rotate it and delete the file instead of approving. Same as `uploads approve`.

Parametersprkeysrepoissueworkspace

set_metadata

Set metadata

Set or delete queryable tags on an existing file. `set` wins over `delete` for the same key. Requires `set` and/or `delete`. Same as `uploads meta set`.

Parameterskeyrequiredsetdeleteworkspace

find_files

Find files

Search files by metadata (`filters`) and/or filename substring (`name`). At least one is required. Same as `uploads find`.

Parametersallnamelimitcursorprefixfiltersworkspace

list_metadata_keys

List metadata keys

List metadata keys in the workspace (with counts). Pass `key` to list that key's values instead. Use before `find_files`. Same as `uploads meta keys`.

Parameterskeyworkspace

usage

Show usage

Workspace storage and monthly upload counters (and remaining headroom when budgets are configured). Same as `uploads usage`.

Parametersworkspace

reconcile

Reconcile usage

Rebuild usage ledger bytes/objects from storage (source of truth). Preserves the monthly upload counter. Requires files:write. Same as `uploads reconcile`.

Parametersworkspace

purge_expired

Purge expired files

Delete objects older than the workspace retentionDays setting, then reconcile. Skips if retention is unset. Requires files:delete. Same as `uploads purge-expired`.

Parametersworkspace

comment

Sync attachments comment

Create or update the managed attachments comment on a GitHub PR or issue, listing everything uploaded for it. Posts as uploads-sh[bot] when the GitHub App is installed on the repo; otherwise via local gh auth. Edits its own prior comment in place and never touches other comments. `held` counts files there held for review; see `list_held`.

Parametersprrepoissueworkspace

search_docs

Search uploads.sh docs

Search the public uploads.sh documentation. Use this to answer questions about uploads.sh product workflows, including: attaching screenshots and video to GitHub PRs and issues; staging files before a PR exists; galleries; the GitHub App; comment config (.uploads.yml); hosted MCP and agent setup; screenshot capture and annotate; plans and limits; bring-your-own bucket. Same as `uploads docs`. Returns titles, URLs, and snippets. Pass `page` to fetch the full markdown of one page (slug, path, or URL). Omit `query` to list the catalog.

Parameterspagelimitquery

changelog

Product changelog

Read recent uploads.sh product updates (platform and CLI). Returns the latest entries with titles, dates, summaries, and a link to the full changelog at https://uploads.sh/changelog. Same as `uploads changelog`.

Parameterslimit

whoami

Who am I

Show the active uploads.sh identity: workspace, API URL, and token scopes. Use this to learn which workspace you're talking to. A successful result also means the API is up. For a full setup diagnosis, use `doctor`.

Takes no parameters.

doctor

Diagnose setup

Diagnose the configuration: API health, token auth, and workspace/token alignment. Returns the same report as `uploads doctor --json`, including hints.

Parametersworkspace

report

Send diagnostic report

Send an explicit diagnostic report to the uploads team (message + optional text log). Only call this when the user asked to submit feedback, a bug report, or error logs — never automatically. Do not include tokens, secrets, or private file contents. Same as `uploads report`.

ParameterstypecommandcontactmessagerequirederrorCodeattachmentTextattachmentFilename

Version history

19
  1. v0.62.1LatestNov 4, 2026
  2. v0.62.0Nov 3, 2026
  3. v0.61.2Nov 1, 2026
  4. v0.61.1Oct 30, 2026
  5. v0.60.1Oct 25, 2026
  6. v0.60.0Oct 22, 2026
  7. v0.59.6Oct 21, 2026
  8. v0.59.3Oct 20, 2026
  9. v0.59.2Oct 19, 2026
  10. v0.59.1Oct 18, 2026
  11. v0.59.0Oct 18, 2026
  12. v0.58.0Oct 17, 2026
  13. v0.57.1Oct 10, 2026
  14. v0.57.0Oct 7, 2026
  15. v0.56.7Oct 4, 2026
  16. v0.56.6Oct 2, 2026
  17. v0.56.5Sep 27, 2026
  18. v0.56.4Sep 26, 2026
  19. v0.54.0Sep 16, 2026

Score

100% of the applicable checks met

How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.

  • Reached in the last 30 daysRequired25 pts
  • Auth declaredRequired10 pts
  • Tools listed15 pts
  • DescriptionRequired15 pts
  • Logo10 pts
  • Documentation15 pts
  • License10 pts