githubattachlisted
Install: claude install-skill bendrucker/claude
# Attachments
Images and video in issues and pull requests are served from a user-attachments store. `POST https://uploads.github.com/user-attachments/assets` puts a file there and answers with the URL to reference. It has no REST route and no documentation, so `gh api` reaches it by full URL.
## Upload
`repository_id` takes the numeric REST id. `gh repo view --json id` returns the GraphQL node id, which fails here.
```bash
repo_id=$(gh api repos/{owner}/{repo} --jq .id)
gh api --method POST \
"https://uploads.github.com/user-attachments/assets?repository_id=$repo_id&name=picker.png&content_type=image/png" \
--input ./picker.png --jq .url
```
The response is `{"url": "https://github.com/user-attachments/assets/<uuid>"}`.
The token needs write access to that repository. Read-only access answers 404, which makes a permission problem look like a missing repository.
## File Types
The extension in `name` must agree with `content_type`, and nothing outside this list uploads. Logs, archives, and PDFs have no path here.
| Extension | `content_type` |
| --- | --- |
| `.png` | `image/png` |
| `.jpg`, `.jpeg` | `image/jpeg` |
| `.gif` | `image/gif` |
| `.webp` | `image/webp` |
| `.svg` | `image/svg+xml` |
| `.mp4` | `video/mp4` |
| `.mov` | `video/quicktime` |
| `.webm` | `video/webm` |
Images cap at 10 MB. Video caps at 100 MB or lower, depending on the account plan.
## Reference
An image is ordinary markdown, with `\`, `[`, and `]` escaped in the alt text.
```markdow