From claude-resources
Creates GitHub issues with embedded images via CLI by uploading screenshots to a _attachments release and linking asset URLs in the issue body. Use for visual issues or programmatic attachment without browser UI.
npx claudepluginhub takazudo/claude-resources<owner/repo> <title> --body <body> --img <path> [--img <path>...]This skill is limited to using the following tools:
Create GitHub issues with embedded images using release assets as image hosting.
Guides Next.js Cache Components and Partial Prerendering (PPR): 'use cache' directives, cacheLife(), cacheTag(), revalidateTag() for caching, invalidation, static/dynamic optimization. Auto-activates on cacheComponents: true.
Guides building MCP servers enabling LLMs to interact with external services via tools. Covers best practices, TypeScript/Node (MCP SDK), Python (FastMCP).
Share bugs, ideas, or general feedback.
Create GitHub issues with embedded images using release assets as image hosting.
GitHub CLI does not support attaching images to issues natively. This skill works around that by uploading images to a dedicated release, then embedding the asset URLs in the issue body markdown.
Arguments: <owner/repo> <title> --body <body> --img <path> [--img <path>...]
Multiple --img flags supported. If no --body, use empty string.
Extract from the skill arguments:
owner/repo (required) - the target repository--body (optional) - issue body text--img (one or more) - paths to image filesCheck for a non-draft release tagged _attachments in the repo. Create if missing.
If an old draft _attachments release exists (from before this fix), delete it first — draft releases don't have tags, so assets uploaded to them return 404 for unauthenticated access.
# Check if a tagged (non-draft) release exists
gh release view _attachments --repo <owner/repo> 2>/dev/null
# If it doesn't exist, check for and clean up any old draft release named "_attachments"
# (Draft releases have no tag, so we search by title via the API)
OLD_DRAFT_ID=$(gh api repos/<owner/repo>/releases --jq '.[] | select(.draft == true and .name == "_attachments") | .id' 2>/dev/null)
if [ -n "$OLD_DRAFT_ID" ]; then
gh api -X DELETE repos/<owner/repo>/releases/$OLD_DRAFT_ID
fi
# Create the non-draft release (NOT --draft — draft assets require auth and return 404 for anonymous access)
gh release create _attachments --title "_attachments" --notes "Image attachments for issues. Do not delete." --repo <owner/repo>
For each --img path, generate a unique filename to avoid collisions, then upload.
# Generate unique name: timestamp + original filename
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
UNIQUE_NAME="${TIMESTAMP}-$(basename <path>)"
# Upload
gh release upload _attachments "<path>#${UNIQUE_NAME}" --repo <owner/repo> --clobber
Important: The #name syntax renames the asset on upload. Use --clobber to overwrite if name collision occurs.
If gh release upload does not support the #name rename syntax, copy the file to a temp location with the unique name instead:
TMPFILE="/tmp/${UNIQUE_NAME}"
cp "<path>" "$TMPFILE"
gh release upload _attachments "$TMPFILE" --repo <owner/repo> --clobber
rm "$TMPFILE"
Fetch the download URLs for uploaded assets.
gh api repos/<owner/repo>/releases/tags/_attachments \
--jq '.assets[] | select(.name == "<UNIQUE_NAME>") | .browser_download_url'
Append image markdown to the body:
<original body text>

For multiple images, add each on its own line.
gh issue create \
--repo <owner/repo> \
--title "<title>" \
--body "$(cat <<'EOF'
<constructed body with embedded images>
EOF
)"
Print the created issue URL.
_attachments release is a real (non-draft) release so asset URLs are publicly accessible without authentication--draft — draft release assets return 404 for unauthenticated requests (e.g., Claude API vision, curl), even though they appear to work in browsers where the user is logged in