From theclauu
Use when an analyst wants to file a GitHub issue with a screenshot against a GitHub repo. Expected inputs: a screenshot, a short description, the target repo, and the page URL or app section where the issue was observed (the skill prompts for the URL if missing).
npx claudepluginhub artemis-xyz/theclauu --plugin theclauuThis skill uses the workspace's default tool permissions.
Turn a screenshot + a short description into a well-structured GitHub issue on the target repo. Images are committed to `artemis-xyz/issue-attachments` (a public, unlisted-by-path repo) and embedded in the issue body via their raw URLs.
Generates design tokens/docs from CSS/Tailwind/styled-components codebases, audits visual consistency across 10 dimensions, detects AI slop in UI.
Records polished WebM UI demo videos of web apps using Playwright with cursor overlay, natural pacing, and three-phase scripting. Activates for demo, walkthrough, screen recording, or tutorial requests.
Delivers idiomatic Kotlin patterns for null safety, immutability, sealed classes, coroutines, Flows, extensions, DSL builders, and Gradle DSL. Use when writing, reviewing, refactoring, or designing Kotlin code.
Turn a screenshot + a short description into a well-structured GitHub issue on the target repo. Images are committed to artemis-xyz/issue-attachments (a public, unlisted-by-path repo) and embedded in the issue body via their raw URLs.
Reference files:
body-template.md — issue body structure, title rules, proposed-label logic.Follow these steps exactly in order. If any prerequisite fails, stop and surface the error — do not improvise around it.
Trigger: the analyst invoked /file-github-issue [repo], or wrote ambient prose containing at least one image AND a filing-intent phrase ("open an issue", "report this", "log a bug", "file a bug", "file an issue"). If neither the image nor a filing phrase is present, ask the analyst to confirm intent and halt.
Collect:
owner/repo slug. If bare (e.g., huntress), resolve to artemis-xyz/<name> — the common case for our analysts. Record the resolved slug; every subsequent step uses it. Existence and access are verified implicitly by the label pre-flight (step 3) and the final gh issue create — no separate allowlist..png, .jpg, .jpeg, .gif, or .webp (case-insensitive). Reject any other extension with a clear error naming the rejected path and the accepted set, then halt.gh must be installed and authenticated. If gh --version fails: error with brew install gh hint. If gh auth status fails: error with gh auth login hint.Run once the target repo is known, BEFORE rendering the preview (and again if a later edit changes the target repo):
gh label list --repo <repo-slug> --json name --jq '.[].name'
Intersect the command output with the proposed label set (see body-template.md) to get the effective label set. Record labels that were proposed but not present in the repo as dropped — they'll be shown inline in the preview and repeated as a post-filing warning.
If the pre-flight command itself fails (network, rate limit, non-zero exit): do not abort. Fall back to sending all proposed labels unchanged and note in the preview: "(label pre-flight unavailable; all proposed labels will be attempted)".
Lean toward richer context. The issue body is only as useful as what you pull in here. Don't fabricate — if a field has no source, prompt the analyst (for the Page/URL anchor, see 4b.5) or omit it (for optional enrichers like Action, Inputs, Links).
4a. Extract from the screenshot(s). Read each image carefully and pull:
## What I saw).4b. Extract from the analyst prose. Pull:
#123, artemis-xyz/foo#45).4b.5. Prompt for URL if missing. Decide whether 4a + 4b produced a concrete Page/URL anchor. Concrete means: a browser URL visible in the screenshot chrome, a URL-shaped string in the prose, or an app + section + specific surface in the screenshot (e.g., "Huntress — entity page — NVDA"). Just an app name ("Huntress") or an app + generic surface ("Huntress — dashboard") is NOT enough on its own. If nothing concrete, halt and ask:
I don't see a URL or page anchor in the screenshot or your description. What page is this from? Paste the URL or describe the surface — e.g.,
huntress.artemis.internal/dashboardor "Huntress entity page for NVDA".
Wait for a reply. Use it as the Page/URL value.
unknown — analyst declined to provide. This makes the informed choice explicit rather than making it look like the skill forgot to ask.4c. Dupe and related-issue search. Run once, against the target repo (re-run if target repo changes during Step 5 edits). Use 2–3 salient keywords from the analyst prose and screenshot (the draft title doesn't exist yet — it's produced in 4d):
gh issue list --repo <repo-slug> --search "<2-3 keywords>" --state all --limit 10 --json number,title,state
Include any clearly related hits in the ## Related > Issues bullet with their state and a one-line relationship note. If the search returns nothing germane, the bullet is "none found" (or omit if there are also no Links).
If there's an obviously open duplicate with the same framing, do NOT silently file a second one — raise it in the preview and let the analyst choose (comment on the existing issue vs. file anyway with a cross-reference).
4d. Draft. Produce title, body, and proposed labels per body-template.md. Pick the single-image template if exactly one image was attached, otherwise the multi-image template. Leave <attachment-url-N> placeholders literal — they're substituted in step 6.
Render exactly this block:
Screenshot(s) will be committed to artemis-xyz/issue-attachments (public repo; unlisted-by-path). Anyone with the URL can view. Cancel now if redaction is needed.
------------------------------------------
Target repo: <repo-slug>
Title: <title>
Labels: <effective set> (dropped: <comma-separated>, if any)
Body:
<full rendered markdown; each <attachment-url-N> placeholder shown as "(uploaded on confirm)" — for single-image render as "", for multi as "", etc.>
------------------------------------------
File this? [y / n / or describe edits]
Keep the <attachment-url-N> tokens in the internal body string — only the preview hides them behind the stub. The real URLs are swapped in after y (step 6).
Wait for the analyst's reply:
y → proceed to step 6.n or cancel → exit cleanly. No commit, no issue./file-github-issue invocation — cancel this one and restart.Only run after the analyst replies y.
Images are committed to artemis-xyz/issue-attachments on the main branch at <YYYY>/<MM>/<uuid>.<ext>. Each image gets a fresh UUID so paths don't collide and aren't guessable by enumeration.
For each image (in turn order):
EXT="${IMG_PATH##*.}" # e.g. "png"
UUID=$(uuidgen | tr '[:upper:]' '[:lower:]')
ATTACH_PATH="$(date +%Y)/$(date +%m)/$UUID.$EXT"
jq --rawfile — passing the base64 as a --arg value still puts it on the command line and blows past ARG_MAX on anything over ~100KB:
B64_FILE=$(mktemp "${TMPDIR:-/tmp}/file-github-issue-b64.XXXXXX")
base64 -i "$IMG_PATH" | tr -d '\n' > "$B64_FILE"
jq -n --arg msg "file-github-issue attachment: <title>" \
--rawfile content "$B64_FILE" \
'{message: $msg, content: $content}' \
| gh api --method PUT \
"/repos/artemis-xyz/issue-attachments/contents/$ATTACH_PATH" \
--input -
rm "$B64_FILE"
ATTACH_URL="https://raw.githubusercontent.com/artemis-xyz/issue-attachments/main/$ATTACH_PATH"
<attachment-url-N> placeholder matching this image's turn position (image 1 → <attachment-url-1>, image 2 → <attachment-url-2>, etc.) with this image's $ATTACH_URL.If any upload fails: abort before filing. Print the attachment URLs of any images already committed — they're persistent and re-usable. No rollback.
Max file size: the Contents API hard-limits at 100MB. For files over ~1MB the API also warns — still works for typical screenshots (well under), but if you hit a size error, surface it and halt.
mktemp on macOS requires XXXXXX at the end of the template — no .md suffix; gh --body-file doesn't care about extension:
TMPFILE=$(mktemp "${TMPDIR:-/tmp}/file-github-issue.XXXXXX")
gh issue create \
--repo <repo-slug> \
--title "<title>" \
--body-file "$TMPFILE" \
[--label <effective-label-1>] [--label <effective-label-2>] ...
rm "$TMPFILE".gh stdout) and the attachment URL(s). If any labels were dropped in step 3, repeat the warning:
⚠ Filed without labels (target repo missing:
<comma-separated>). Create them in the repo to enable labeling next time.
If gh issue create fails (e.g., 403/404 for missing permissions): surface the exact gh stderr and suggest requesting access. The attachment URLs are preserved — print them so the analyst can reuse or delete (delete via gh api --method DELETE /repos/artemis-xyz/issue-attachments/contents/<path> with the file's blob SHA).
Two surfaces, same body underneath:
/file-github-issue [repo]. Arg optional — if missing, ask. Accepts bare name (defaults to artemis-xyz/<name>) or a full owner/repo slug.| Failure | Behavior |
|---|---|
| No image in the turn | Ask for one. Do not proceed. |
| Unsupported image format (not png/jpg/jpeg/gif/webp) | Error listing the rejected path and the accepted formats. Halt. |
| Image file unreadable / corrupt / empty | Error with the path. Ask to re-provide. Halt. |
gh not installed | Error with brew install gh hint. Exit. |
gh auth status fails | Error with gh auth login hint. Exit. |
| Target repo doesn't exist (404 at label pre-flight or issue create) | Surface gh stderr (404). Re-prompt the analyst for the correct repo. |
| Analyst lacks issue:write on target repo | Surface gh stderr, suggest requesting access. Attachment URLs preserved — print them. |
Analyst lacks write on artemis-xyz/issue-attachments | Surface gh stderr, suggest requesting access. Halt before filing. |
| Body mentions a repo different from target | Warn inline in the preview; do not block. Analyst is authoritative. |
| Contents API commit fails | Abort before gh issue create. Print error. |
| Image exceeds 100MB Contents API limit | Surface the error. Suggest compressing or using a smaller screenshot. Halt. |
| Issue creation fails after attachment upload | Print the orphaned attachment URLs. They're reusable if refiled. |
| Proposed label missing in repo | Caught by pre-flight (step 3). Dropped labels shown in preview and repeated post-filing. |
gh label list pre-flight fails | Don't abort. Send all proposed labels. Note in preview. |
| Analyst cancels at preview | Exit cleanly. No commit, no issue. |
| Analyst interrupts mid-upload | No partial-cleanup guarantee. Already-committed images remain in the attachments repo. |
| Multi-image, any one upload fails | Abort all. Print already-committed attachment URLs so they can be reused or deleted. |
--body-file: avoids shell-escaping pain with markdown (backticks, newlines, special chars).gh issue create fails on a missing label, stripping all --label flags would also drop the valid ones. Pre-flight gives a clean, one-round answer.gh gist create only accepts text files — binaries like PNGs are rejected. GitHub has no public API for inline issue attachments (the web UI's paste-image flow uses a private session-cookie endpoint). Committing to a public repo and embedding the raw URL is the only gh-reachable path that renders inline. Public is required because raw URLs from private repos go through signed, short-lived redirects that don't render in issue markdown. Secrecy is by-path: each image gets a fresh UUID, so the URL isn't guessable.jq --rawfile (not --arg or -f content=…): base64-encoded images blow past ARG_MAX on anything over ~100KB. Both jq --arg content "$(base64 ...)" and gh api -f content=… shell-expand the value onto the command line and fail with "argument list too long". --rawfile reads from a file descriptor, so the payload never touches argv.https://github.com/artemis-xyz/issue-attachments/tree/main/<YYYY>/<MM>/ or gh api /repos/artemis-xyz/issue-attachments/git/trees/main?recursive=1 --jq '.tree[].path'.If you catch yourself thinking any of these, STOP — you are about to file an issue that will land badly:
y.Related > Issues bullet. Still your job to read them and decide: if an open issue already covers this exactly, raise it in the preview and let the analyst choose (comment vs. file with cross-reference). Never silently file a second copy.| Excuse | Reality |
|---|---|
| "I can tell from the screenshot which repo" | Maybe, maybe not. The analyst is authoritative. Ask if unsure. |
| "The sparse warning is ugly, I'll drop it" | The warning is the feature — it nudges the analyst to add context before filing. |
| "I'll guess the URL from the app name" | Don't. Step 4b.5 prompts the analyst explicitly when extraction fails. Use their reply. Fabricated URLs are worse than missing ones. |
| "I'll skip the 4b.5 prompt, they can fix it in the preview" | No. The preview is for reviewing the draft, not for remembering missing anchors. Asking once upfront is cheaper than the analyst catching an "unknown" placeholder in the preview and re-triggering an edit round. |
| "The Related section is empty, I'll invent a tangentially-related issue" | No. If the dupe search found nothing and there are no links in the prose, omit the section entirely per body-template.md. |
| "I'll swap in the real attachment URLs now to save a step" | No. Commit happens only after y. A cancelled preview should never leave an attachment in the repo. |
| "Missing label? I'll create it" | Out of scope. Ship the issue without the label; flag the gap in the post-filing warning. |
"I'll just use cat <<EOF | gh issue create --body -" | Backticks and pipes in markdown break this. Always --body-file. |
| "The pre-flight failed, I'll bail" | Don't. Fall back to sending all proposed labels and note it in the preview. |
| "The analyst's 4b.5 reply is terse / unhelpful, I'll reword or expand it" | No. One prompt, one reply. Use the reply verbatim. If it's wrong, the analyst will fix it in the preview edit round. |
| "The analyst changed the target repo in preview edits, the old dupe results probably still apply" | No. Dupe search is repo-scoped. Re-run step 4c alongside step 3 whenever the target repo changes. |
| "The analyst wants to swap the screenshot, I'll just attach it in the preview edit" | No. Edit rounds change text and metadata only. For image changes, cancel and restart /file-github-issue. |