Best practices for creating GitHub pull requests that include inline images — CLI terminal screenshots (from cli-demo-recorder), UI screenshots/videos (from ui-demo-recorder), or any other visual artifact. Use this skill whenever opening or updating a PR that has visual artifacts to embed, or when images aren't rendering in a PR description. Also use it when asked "how do I add screenshots to a PR", "why isn't my image showing", or "embed a demo in the PR".
Scanned 9/1/2026
Install to Claude Code
npx -y skills add PackmindHub/packmind --skill michel-create-pr-with-screenshots --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Michel Create Pr With Screenshots?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/packmindhub-michel-create-pr-with-screenshots)More formats (shields.io, HTML) on the badges page.
---
name: michel-create-pr-with-screenshots
description: Best practices for creating GitHub pull requests that include inline images — CLI terminal screenshots (from cli-demo-recorder), UI screenshots/videos (from ui-demo-recorder), or any other visual artifact. Use this skill whenever opening or updating a PR that has visual artifacts to embed, or when images aren't rendering in a PR description. Also use it when asked "how do I add screenshots to a PR", "why isn't my image showing", or "embed a demo in the PR".
---
# Create PR with Screenshots
GitHub PR descriptions behave differently from README files: **relative paths don't resolve** and **SVG files don't render** (sanitized for XSS). This skill codifies the two-step fix every time: convert to PNG, reference with an absolute raw URL pinned to the commit SHA.
> **Running as the Michel agent?** You do NOT build these URLs by hand. Write the PR body with the literal `<!-- ARTIFACTS_PLACEHOLDER -->` token (see the implementation prompt's `## Artifacts` section) and drop every file under `.agent/artifacts/issue-<N>/`. The publish step lists each file and injects correctly-formed, SHA-pinned image/video markup at the token. Hand-writing paths or `` there renders as dead text and the artifacts are lost. The rest of this skill is for the manual case — opening a PR yourself.
>
> The publish step (`fly/lib/phases/publish.sh`) **owns the entire `## Artifacts` section**: it injects the generated block at the heading and discards every line under it — any relative-path images, stray tokens, or hand-written subsections — up to the next `## ` heading. So hand-written junk there is now wiped rather than shipped (it used to survive next to the injected block — see PR #41, where a hand-written `### Screenshots` block with `` paths rendered as broken images). This is a backstop, not a license: still emit only the bare token.
## The core rule
| Artifact | Renders in PR? | Fix |
| -------------------------------- | --------------------------- | --------------------- |
| PNG via raw URL pinned to SHA | ✅ | nothing |
| PNG via raw URL pinned to branch | ⚠️ dies when branch deleted | pin to the commit SHA |
| PNG via relative path | ❌ | use absolute URL |
| SVG via raw URL | ❌ (blocked by GitHub CSP) | convert to PNG first |
| WebM / MP4 video | ❌ inline | link, don't embed |
On a **private repo**, raw URLs render only for viewers who are logged-in members — fine for internal PR review (the curl-with-token test below will 404 because the `/raw/` route wants a browser session, not a PAT — that's expected, not a failure). There is no anonymous fallback short of uploading the file as a GitHub user-attachment via the web composer.
## Step-by-step
### 1. Get a PNG
**From cli-demo-recorder (SVG output)**
The recorder writes SVG. Convert it to PNG before committing:
```bash
# macOS
qlmanage -t -s 1400 -o docs/cli-demos/ docs/cli-demos/my-demo.svg
# produces docs/cli-demos/my-demo.svg.png — rename for clarity:
mv docs/cli-demos/my-demo.svg.png docs/cli-demos/my-demo.png
```
```bash
# Linux (install once: apt install librsvg2-bin)
rsvg-convert -w 1400 docs/cli-demos/my-demo.svg -o docs/cli-demos/my-demo.png
```
Keep the SVG in the repo (crisp at any zoom in README/docs). Commit **both** — SVG for docs, PNG for PR.
**From ui-demo-recorder (PNG screenshots)**
The recorder already produces PNGs — no conversion needed. They land in `screenshots/` or `.agent/artifacts/`.
### 2. Commit the PNG to the branch
```bash
git add docs/cli-demos/my-demo.png
git commit -m "..."
git push
```
The file must be pushed before the URL resolves. GitHub serves uncommitted files as 404.
### 3. Build the absolute raw URL — pinned to the commit SHA
```
https://github.com/<owner>/<repo>/raw/<commit-sha>/<path-to-file>
```
Pin to the **commit SHA**, not the branch. `raw/<branch>/...` 404s the moment the branch is deleted on merge — silently breaking every image in an already-merged PR. The SHA-pinned blob lives in history forever.
Example:
```
https://github.com/PackmindHub/packmind/raw/9f3c1ab2/docs/cli-demos/my-demo.png
```
Get owner/repo/sha from:
```bash
git remote get-url origin # → https://github.com/PackmindHub/packmind
git rev-parse HEAD # → 9f3c1ab2... (the pushed commit that holds the file)
```
### 4. Embed in the PR body
````markdown
## CLI demo

<details><summary>Plain text</summary>
```text
<paste .txt sidecar content here>
```
````
</details>
```
For **multiple images**, group them logically — one caption per image, collapsed plain-text fallback for each:
```markdown
**Populated board:**

**Empty board:**

```
For **WebM videos** (from ui-demo-recorder): GitHub doesn't play video inline in PR descriptions. Link it instead:
```markdown
[▶ demo.webm](https://github.com/<owner>/<repo>/raw/<commit-sha>/videos/demo.webm) (click to play/download)
```
## Quick checklist
Before opening/updating the PR:
- [ ] PNG committed and pushed (not just SVG)
- [ ] URL uses `https://github.com/<owner>/<repo>/raw/<commit-sha>/...` (absolute + SHA-pinned, not relative, not branch-pinned)
- [ ] The SHA in the URL is a commit that's been pushed (`git rev-parse HEAD` after push)
- [ ] Verify by opening the URL in a browser **while logged in** — a 404 means the file isn't pushed (or, on a private repo via curl+PAT, just that the route needs a session — check in the browser)
## Where to store images
| Source | Recommended path |
| ---------------------------- | ------------------------------------------------------------------- |
| cli-demo-recorder | `docs/cli-demos/<name>.png` |
| ui-demo-recorder (manual PR) | `docs/screenshots/<name>.png` |
| Michel agent artifacts | `.agent/artifacts/issue-<N>/<name>.png` (agent writes here already) |
Pick a stable path — the URL in old PR descriptions will keep pointing there forever.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!