Uploads PR and validation media to a self-hosted attach Worker via the installed attach CLI (`attach` or `gh attach`): zero-config hosted device-flow login with an ATTACH_GITHUB_CLIENT_ID override for custom deployments, put/delete/logout of screenshots and artifacts, preview `/p/…` URLs, raw `/o/…` embeds via `--markdown`, and `--json`/`--url` output; or GitHub App JWT enroll then `att_` PUT for agents. Use when the user asks to attach a screenshot, upload PR media, put an image on attach.uinaf.dev (or ATTACH_API_BASE), share a validation screenshot URL, run attach login/put/delete/logout, use gh attach, host validation media, take down attach media, or enroll an App agent for attach. Do not use for Worker deploy, vault, Cloudflare ops, or inventing a second upload client.
—
—
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
For automation that already has a GitHub App private key. Not wired into the
attach CLI binary — use HTTP enroll, then upload with the minted att_ key.
AGENT_REGISTRYATTACH_API_BASE / public host matching Worker ATTACH_PUBLIC_BASESign RS256 (optional kid) with claims:
| Claim | Value |
|---|---|
iss | attach:<github_app_id> |
aud | public attach host (e.g. attach.uinaf.dev) — same origin as ATTACH_API_BASE |
exp | ≤ iat + 120 |
jti | fresh UUID (one-time; Durable Object claims it) |
Reject any flow that uses bare GitHub API JWTs, jku, or remote JWKS.
Prefer language-native HTTP (fetch, etc.) that sets Authorization from
memory and parses JSON in-process — never put the bearer in argv, never print
att_ to chat or logs.
If you must use curl, use a per-step EXIT trap (clear it before the next step so traps do not stack across enroll → put):
base="${ATTACH_API_BASE:-https://attach.uinaf.dev}"
hdr="$(mktemp)"; out="$(mktemp)"
trap 'rm -f "$hdr" "$out"' EXIT
printf 'Authorization: Bearer %s\nAccept: application/json\n' "$ATTACH_AGENT_JWT" >"$hdr"
curl -sS -X POST "$base/v1/enroll/agent" -H @"$hdr" -o "$out"
# parse "$out" in-process for .token → secret var only
rm -f "$hdr" "$out"; trap - EXITExpect JSON with token (att_…), key_id, principal (app:<id>). If the
response indicates the principal is disabled, hard-fail.
Same rules: prefer native HTTP. Curl pattern:
base="${ATTACH_API_BASE:-https://attach.uinaf.dev}"
hdr="$(mktemp)"; out="$(mktemp)"
trap 'rm -f "$hdr" "$out"' EXIT
printf 'Authorization: Bearer %s\nContent-Type: image/png\n' "$ATTACH_ATT_TOKEN" >"$hdr"
curl -sS -X PUT "$base/v1/objects" -H @"$hdr" --data-binary @"$FILE" -o "$out"
# read url + preview_url from "$out" only
rm -f "$hdr" "$out"; trap - EXITOptional repo / pr metadata per Worker/CLI contract. Success only when the
JSON includes both url (raw /o/…) and preview_url (/p/…).
On 401 from put: mint a new JWT (jti), enroll once, put again. If enroll
fails because the principal is disabled, or a second put still returns 401,
hard-fail — do not loop.
Never log PEM material or att_ values. Prefer returning preview_url to
humans; use raw url for markdown embeds. Token rules for put live in the
skill Hard rules section.