Files
awesome-copilot/skills/github-issues/references/images.md
Tadas Labudis fca5de1f6a Improve github-issues skill: fix MCP tools, add search reference, fix sub-issues docs (#888)
* Add advanced search reference with query syntax guide

Covers search qualifiers, boolean logic, date ranges, missing metadata
filters, common patterns, and when to use search vs list_issues.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add issue fields search support to search and issue-fields references

- Add Advanced Search Mode section to search.md covering field: qualifier,
  has:field: syntax, REST advanced_search=true, and GraphQL ISSUE_ADVANCED
- Add Searching by Field Values section to issue-fields.md with REST/GraphQL
  examples and qualifier reference table
- Note MCP search_issues limitation (no advanced_search support)
- Update SKILL.md capability table to mention issue field filters

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Clarify three search approaches: list_issues vs search_issues vs advanced search

Replace the simple two-column comparison with a capability matrix showing
what each approach supports (field filters, boolean logic, scope, etc.)
and a decision guide for when to use each one.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix issue field search syntax: use dot notation (field.name:value)

The colon notation (field:Name:Value) is silently ignored by the API.
The correct syntax is dot notation (field.priority:P0) which works in
REST (advanced_search=true), GraphQL (ISSUE_ADVANCED), and web UI.

Also supports has:field.name, no:field.name, and date comparisons.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix github-issues skill: correct MCP tools and add gh api workflows

The skill listed 5 MCP tools that don't exist (create_issue, update_issue,
get_issue, add_issue_comment, list_issue_types), causing tool-not-found
errors when agents tried to follow the skill instructions.

Changes:
- Split tools table into MCP (read ops) and CLI/API (write ops)
- Add gh api commands for creating, updating, commenting on issues
- Document that gh issue create doesn't support --type flag
- Add GraphQL query for discovering issue types
- Remove redundant [Bug]/[Feature] title prefixes (use type param instead)
- Update examples to use gh api instead of non-existent MCP tools

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix sub-issues reference: add gh api examples and integer gotcha

The sub_issue_id parameter requires an integer but gh api -f sends strings,
causing 422 errors. Updated all REST examples to use --input with raw JSON.

Also added:
- Recommended two-step workflow (create issue, then link)
- Explicit warning about -f vs --input for integer params
- Proper gh api command syntax instead of raw HTTP notation

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Address PR review: fix search docs accuracy and broken link

- Fix misleading claim about full boolean logic support (implicit AND only)
- Remove sort:updated from query example (it's an API param, not a qualifier)
- Clarify -linked:pr comment to avoid confusion with authoring status
- Fix relative link in issue-fields.md (sibling file, not nested path)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Improve projects reference: scope warning, gh api examples, issue-side queries

From hands-on usage: hit INSUFFICIENT_SCOPES trying to update project
status because token had read:project but not project write scope.

Added:
- OAuth scope requirements table with gh auth refresh workaround
- How to find an issue's project item ID (query from issue side)
- All GraphQL examples now use gh api graphql (copy-paste ready)
- End-to-end example: set issue status to In Progress

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add images-in-issues reference: hosting methods, pitfalls, screenshots

Documents three approaches for embedding images in issue comments
via CLI: Contents API with github.com/raw/ URLs, browser drag-drop
for permanent user-attachments URLs, and gist hosting limitations.

Includes puppeteer screenshot recipe and comparison table.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Update README.skills.md with images reference

Run npm run build to regenerate skill listing.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix issue-fields search: add GraphQL bulk query, caveat search syntax

The field.name:value search qualifier is unreliable via API (returns
0 results even when matching issues exist). Added a recommended
GraphQL approach that fetches issues and filters by issueFieldValues
client-side. Documented the correct IssueFieldSingleSelectValue
schema (name, not value). Marked search qualifier syntax as
experimental with a reliability warning.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* docs(github-issues): improve project discovery guidance

The projectsV2 query param does keyword search, not exact match,
and sorts by recency. For large orgs like github, common words like
'issue' return 400+ results and bury the target project.

Added a priority-ordered discovery strategy:
1. Direct lookup by number (instant)
2. Reverse lookup from a known issue's projectItems (most reliable)
3. GraphQL name search with client-side jq filtering (fallback)
4. MCP tool (small orgs only)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-06 21:20:36 +11:00

4.7 KiB

Images in Issues and Comments

How to embed images in GitHub issue bodies and comments programmatically via the CLI.

Methods (ranked by reliability)

Push image files to a branch in the same repo, then reference them with a URL that works for authenticated viewers.

Step 1: Create a branch

# Get the SHA of the default branch
SHA=$(gh api repos/{owner}/{repo}/git/ref/heads/main --jq '.object.sha')

# Create a new branch
gh api repos/{owner}/{repo}/git/refs -X POST \
  -f ref="refs/heads/{username}/images" \
  -f sha="$SHA"

Step 2: Upload images via Contents API

# Base64-encode the image and upload
BASE64=$(base64 -i /path/to/image.png)

gh api repos/{owner}/{repo}/contents/docs/images/my-image.png \
  -X PUT \
  -f message="Add image" \
  -f content="$BASE64" \
  -f branch="{username}/images" \
  --jq '.content.path'

Repeat for each image. The Contents API creates a commit per file.

Step 3: Reference in markdown

![Description](https://github.com/{owner}/{repo}/raw/{username}/images/docs/images/my-image.png)

Important: Use github.com/{owner}/{repo}/raw/{branch}/{path} format, NOT raw.githubusercontent.com. The raw.githubusercontent.com URLs return 404 for private repos. The github.com/.../raw/... format works because the browser sends auth cookies when the viewer is logged in and has repo access.

Pros: Works for any repo the viewer has access to, images live in version control, no expiration. Cons: Creates commits, viewers must be authenticated, images won't render in email notifications or for users without repo access.

2. Gist hosting (public images only)

Upload images as files in a gist. Only works for images you're comfortable making public.

# Create a gist with a placeholder file
gh gist create --public -f description.md <<< "Image hosting gist"

# Note: gh gist edit does NOT support binary files.
# You must use the API to add binary content to gists.

Limitation: Gists don't support binary file uploads via the CLI. You'd need to base64-encode and store as text, which won't render as images. Not recommended.

3. Browser upload (most reliable rendering)

The most reliable way to get permanent image URLs is through the GitHub web UI:

  1. Open the issue/comment in a browser
  2. Drag-drop or paste the image into the comment editor
  3. GitHub generates a permanent https://github.com/user-attachments/assets/{UUID} URL
  4. These URLs work for anyone, even without repo access, and render in email notifications

Why the API can't do this: GitHub's upload/policies/assets endpoint requires a browser session (CSRF token + cookies). It returns an HTML error page when called with API tokens. There is no public API for generating user-attachments URLs.

Taking screenshots programmatically

Use puppeteer-core with local Chrome to screenshot HTML mockups:

const puppeteer = require('puppeteer-core');

const browser = await puppeteer.launch({
  executablePath: '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
  defaultViewport: { width: 900, height: 600, deviceScaleFactor: 2 }
});

const page = await browser.newPage();
await page.setContent(htmlString);

// Screenshot specific elements
const elements = await page.$$('.section');
for (let i = 0; i < elements.length; i++) {
  await elements[i].screenshot({ path: `mockup-${i + 1}.png` });
}

await browser.close();

Note: MCP Playwright may not connect to localhost due to network isolation. Use puppeteer-core with a local Chrome installation instead.

Quick reference

Method Private repos Permanent No auth needed API-only
Contents API + github.com/raw/
Browser drag-drop (user-attachments)
raw.githubusercontent.com (404)
Gist Public only (no binary)

Common pitfalls

  • raw.githubusercontent.com returns 404 for private repos even with a valid token in the URL. GitHub's CDN does not pass auth headers through.
  • API download URLs are temporary. URLs returned by gh api repos/.../contents/... with download_url include a token that expires.
  • upload/policies/assets requires a browser session. Do not attempt to call this endpoint from the CLI.
  • Base64 encoding for large files can hit API payload limits. The Contents API has a ~100MB file size limit but practical limits are lower for base64-encoded payloads.
  • Email notifications will not render images that require authentication. If email readability matters, use the browser upload method.