github-attach-media
Upload an image, screenshot, or video to get a renderable GitHub user-attachments URL for a PR, issue, comment, or Projects card, including private repos (no…
Skill by RascalTwo
Install
Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.
npx agentmarket install skill/rascaltwo-github-attach-media
Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.
Get the weekly diff
The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.
About
Use cases: backend
Reviews
Write a reviewNo reviews yet. Installed it? Reviews come from verified installers only. How reviews work
Permissions
What this skill can do and what it asks for, from its SKILL.md and code. Checked Oct 26, 2026.
- Tools
- No tools found
- Secrets
- None asked for
- Install scripts
- None found
- Runs as
- Node.js package
Network hosts it talks to 1
codeload.github.com· found in install command
Files it touches
~/.claude/skills/github-attach-media
What's inside
- Skill name
github-attach-media- Description
- Upload an image, screenshot, or video to get a renderable GitHub user-attachments URL for a PR, issue, comment, or Projects card, including private repos (no attachment API; raw.githubusercontent won't render). Use when a PR or issue body needs a hosted image.
- License
- MIT
- Instructions
- 88 lines in SKILL.md · view on GitHub
Before installing
- Ships executable scripts
- Instructions call the network
Files (2)
- SKILL.md
- drop-and-harvest.js · scripts/
SKILL.md (first lines)
# GitHub upload: images and video (→ user-attachments CDN URL)
GitHub has **no attachment API**. The only way to get a renderable, access-controlled image URL
is GitHub's own uploader — which is a browser drag-drop onto a classic editor. This skill automates
that with Chrome MCP and hands you a `https://github.com/user-attachments/assets/<uuid>` URL you can
drop into any PR/issue/comment/Projects body via `gh`.
Why not the obvious alternatives:
- **`raw.githubusercontent.com` from a private repo** → does NOT render (camo can't authenticate). Dead end.
- **`file_upload` MCP tool** → currently rejects host paths (regressed). Don't rely on it.
- **Synthetic `cmd+v` paste of a clipboard image** → unreliable; the key event doesn't deliver image
bytes to GitHub's paste handler. Use the **drop** path below instead.
## The mechanism
Put the image on the clipboard as base64 **text**, then dispatch a real `drop` event carrying a
reconstructed `File` onto a classic editor's `<file-attachment>` element. GitHub's real uploader runs
and inserts the `<img src="…user-attachments/assets/…">` markup, which we harvest. The bytes ride the
OS clipboard as text, never through the agent's context.
**Key constraint — you need a CLASSIC editor.** The `<file-attachment>` element only exists on GitHub's
classic Markdown editors, NOT the React `/issues/new` editor. The reliable one is any repo's **wiki new-page**:
`https://github.com/<owner>/<repo>/wiki/_new`. Use it purely as an uploader — **never save the page**;
the asset persists on its own once uploaded.
**Access control / which repo's wiki to use.** A `user-attachments` asset is scoped to whoever can see
the repo it was uploaded through. Prefer the **same repo** as the PR/issue so viewers can see it. If that
repo's wiki is disabled (its `/wiki/_new` redirects to the repo home), use another repo **your audience can
also see** (e.g. another repo in the same org). The asset stays private to those viewers.
## Steps
**1. Put the image on the clipboard as base64 text** (macOS):
```bash
base64 -i /path/to/image.png | tr -d '\n' | pbcopy
```
Note the `-i` — macOS `base64` needs it. (Linux: `base64 -w0 /path/to/image.png | xclip -selection clipboard`.)
**2. Open a classic wiki editor in Chrome** (load Chrome MCP tools first if deferred). Navigate to
`https://github.com/<owner>/<repo>/wiki/_new`, then verify it's really the classic editor:
```js
({ hasFileAttachment: !!document.querySelector('file-attachment'),
hasBody: !!document.querySelector('#gollum-editor-body') })
```
Both must be `true`. If false, the wiki is disabled on that repo — try a different repo's wiki (see access-control note).
**3. Click into the editor body** (the "Page content" textbox) with the `computer` tool — this gives the
tab OS focus, required for `navigator.clipboard.readText()`.
**4. Drop + harvest.** Read `scripts/drop-and-harvest.js` and pass its contents to `javascript_tool`.
It rebuilds the File from the clipboard, dispatches the drop, polls for the URL, and returns
`{ url, imgTag }`. Grab `url`. Pass it **as-is** — it's top-level-await form on purpose; do NOT
re-wrap it in an `async () => {…}` IIFE (the tool returns the last expression but won't await a
Promise you hand back, so a wrapper serializes to `{}`). If you ever do get `{}`, the drop still
ran — just read the body to recover the URL:
`const v=document.querySelector('#gollum-editor-body').value; v.match(/user-attachments\/assets\/[0-9a-f-]+/)?.[0]`
**5. Use the URL.** Set it wherever you need it — the body is plain Markdown/HTML:
```bash
gh pr edit <N> --body "<img width=\"1200\" src=\"$URL\" />\n\n$(cat body.md)"
gh issue edit <N> --body "..."
gh project item-edit --id <DI_…> --body "\n\n<existing>"
```
Prefer building the full body in a file and passing `--body-file` to avoid escaping pain.
**6. Discard the wiki editor — do NOT save.** Clear the body and drop the unsaved-changes guard, then
navigate away:
```js
const b = document.querySelector('#gollum-editor-body');
b.value = ''; b.dispatchEvent(new Event('input', {bubbles:true}));
window.onbeforeunload = null; true;
```
(If you navigate before clearing, Chrome throws a "Leave site?" dialog — clear first.)
## Verify
- **Bytes:** `bytes` in the result equals the file's size. For proof GitHub serves that exact file,
fetch its signed URL (no browser needed) and hash it against the local file:
`U=$(gh api markdown -f mode=gfm -f context=<owner/repo> -f text='' | grep -o 'https://private-user-images[^"]*' | head -1 | sed 's/&/\&/g'); curl -s "$U" | shasum -a256`
- **Page:** navigate to the PR/issue and look: the image renders (broken = wrong repo scope or a
bad URL), a video shows a player. Chrome loads no video in a background tab, and a fresh upload
can take a minute to serve, so a spinner there is not a failed upload; the hash above settles it.
## Notes
- `<img width="1200" height="630" …>` gives a stable render size for a 1200×630 OG card; `` is fine otherwise.
- The asset is permanent and independent of the wiki page — safe to leave the wiki unsaved.
- Several files: repeat steps 1, 3 and 4 per file; the script empties the editor each time.From RascalTwo/ai-setup, MIT.
More from RascalTwo/ai-setup
- 0.603score
okta-api
RascalTwo
Call the Okta REST API to inspect or manage Okta resources (identity providers, users, groups, apps, policies, etc.).
SkillAFreshness: A★ 2Claude Code +9 - 0.603score
model-real-things-3d
RascalTwo
Builds a lifelike 3D model (GLB/glTF) of a real physical object (a PC case, a router, a UPS, furniture) at its true size, and changes it later on request.
SkillAFreshness: A★ 2Claude Code +9 - 0.603score
ai-setup-audit
RascalTwo
Weekly interactive audit of the AI-agent setup shared across Claude Code and OpenAI Codex — AGENTS.md rules, skills, MCP servers, settings, subagents…
SkillAFreshness: A★ 2Claude Code +9 - 0.600score
browser-capture
RascalTwo
Saves screenshots, GIFs, or smooth video of a browser page to disk for docs, PRs, or reports.
SkillAFreshness: A★ 2Claude Code +9 - 0.598score
documandments
RascalTwo
Documentation discipline from the Ten Commandments of Documentation.
SkillAFreshness: A★ 2Claude Code +9 - 0.598score
dredge
RascalTwo
Looks back over a thing's history since the last dredge (sessions, commits, what you pushed back on), judges it with plus-ultra, and brings you every…
SkillAFreshness: A★ 2Claude Code +9 - 0.598score
genui-viz
RascalTwo
Puts a generative UI card in front of the user mid-task (a floating panel glued to their terminal pane) and returns their answer as data: approve a risky…
SkillAFreshness: A★ 2Claude Code +9 - 0.598score
omnissa-horizon-vdi
RascalTwo
Operates a remote desktop through Omnissa Horizon Client on macOS, from Claude Code (computer-use MCP) or Codex (node_repl).
SkillAFreshness: A★ 2Claude Code +9 - 0.598score
aws-creds
RascalTwo
Gets AWS credentials for any AWS account.
SkillAFreshness: A★ 2Claude Code +9 - 0.598score
diagnose-azure-container-app
RascalTwo
Diagnoses why an Azure Container App is failing to start by retrieving system events and application console logs.
SkillAFreshness: A★ 2Claude Code +9 - 0.598score
diagnose-terraform-unknown-error
RascalTwo
Investigates a Terraform provider "unknown error" or opaque API error by adding temporary debug logging to the failing workflow step, triggering a run, and…
SkillAFreshness: A★ 2Claude Code +9 - 0.595score
extract-video-subtitles
RascalTwo
Extracts embedded subtitle/caption tracks (WebVTT/SRT) from a local video file with FFmpeg; falls back to transcribe-media if none exist.
SkillAFreshness: A★ 2Claude Code +9
Signals
- Stars
- 2
- Forks
- 0
- Open issues
- 0
- Last commit (this folder)
- Oct 24, 2026 (4 days ago)
- Last release
- Oct 24, 2026 (4 days ago)
From GitHub (fetched Oct 24, 2026).
Details
- License
- MIT
- Repository
- github.com/RascalTwo/ai-setup
- First seen
- Oct 24, 2026
- Last checked
- Oct 24, 2026
- Source
- GitHubgithub-graphql
More from RascalTwo
- 0.603score
okta-api
RascalTwo
Call the Okta REST API to inspect or manage Okta resources (identity providers, users, groups, apps, policies, etc.).
SkillAFreshness: A★ 2Claude Code +9 - 0.603score
model-real-things-3d
RascalTwo
Builds a lifelike 3D model (GLB/glTF) of a real physical object (a PC case, a router, a UPS, furniture) at its true size, and changes it later on request.
SkillAFreshness: A★ 2Claude Code +9 - 0.603score
ai-setup-audit
RascalTwo
Weekly interactive audit of the AI-agent setup shared across Claude Code and OpenAI Codex — AGENTS.md rules, skills, MCP servers, settings, subagents…
SkillAFreshness: A★ 2Claude Code +9 - 0.600score
browser-capture
RascalTwo
Saves screenshots, GIFs, or smooth video of a browser page to disk for docs, PRs, or reports.
SkillAFreshness: A★ 2Claude Code +9 - 0.598score
diagnose-azure-container-app
RascalTwo
Diagnoses why an Azure Container App is failing to start by retrieving system events and application console logs.
SkillAFreshness: A★ 2Claude Code +9 - 0.598score
aws-creds
RascalTwo
Gets AWS credentials for any AWS account.
SkillAFreshness: A★ 2Claude Code +9
Cite this page
github-attach-media skill. Agent Mart. https://agentmart.dev/skills/rascaltwo-github-attach-media (last updated 2026-10-24)