Attach to ticket
SkillFiles & storageAttach pasted images, files or URLs to a fetched ticket, saved beside its ticket file and referenced from it, or fill an attachment the fetch could not download. Local only, never queries or edits the tracker.
Available today. Use it from your connected AI after setup.
No other account needed.
Add ahel to your AI once: Claude, ChatGPT, Cursor, Claude Code or Codex. Then ask it to use this.
Then ask your AI: use the Attach to ticket skill
What this skill tells your AI
The instructions your AI receives, as published by eai-org/agent-toolkit in skills/attach-to-ticket/SKILL.md and read by ahel’s review.
Save assets — pasted images, local files, URLs — into a ticket's planning directory and reference them from its ticket file, so a fresh session picks them up. Local only — never query or modify the tracker (no API calls, no re-fetch, no comments or edits); downloading an asset URL the user supplies or a not-downloaded entry names is fine, tracker-hosted or not. Edit nothing in the documents beyond the entries below and the REQUIREMENTS line of step 6.
Your task
-
Collect the assets. The images pasted with the invocation, plus paths and URLs in its text; images pasted earlier only when the user points at them. Nothing pasted or pointed at → ask which, listing the images seen in the session. Done when every supplied asset is collected or dropped by the user.
-
Resolve the ticket. Named in the argument or already in the session (fetched, read, discussed) → proceed. Otherwise guess (branch name, latest planning directory) and confirm before writing; nothing to guess from → ask. No planning directory for it yet → stop and point to fetch-ticket; don't create one.
-
Pick the document — unless the user names one: the ticket file, latest
-vN(file or directory) when re-fetched, the<id>-one in a shared directory; the REQUIREMENTS file when no ticket file exists. Several candidates left → ask. -
Map assets to entries. Descriptions map to assets in paste order; "image 2 is …" overrides. If the document has entries whose file is missing (attachments or design references, marked not downloaded or not), propose which asset fills which — by original filename or design name and what the image shows — and confirm, unless the user's text already says. An asset with no description → ask what it shows, recommending a caption read off the image; never write one silently.
-
Save to disk — see Sources; never route bytes through the model (output caps truncate base64 silently). Filling an entry → its filename when that is a bare name (no
/,\,..), else ask; else the nextattachment-<N>.<ext>after the highest N in the document or on disk (<id>-attachment-<N>in a shared directory). Either way the extension follows the actual file type; a symlink at the target, dangling included → ask; never overwrite a valid file. Verify: non-empty; type trailer present where the format has one (PNGIEND, JPEGFFD9, PDF%%EOF), else detected type matches the extension (e.g.file '<path>'); images and PDFs also viewed to confirm they are the asset given. -
Write the entries. Filling an entry: keep it, drop any not-downloaded note, add or rewrite its reference to match the saved file (image → embed, else link; its extension), add the caption line below — one entry per file, never a second. Else append to
## Attachments(create it when missing — last, or before## Design references):### Attachment 3  _<description> — added by hand YYYY-MM-DD_Non-image →
[attachment-3.pdf](attachment-3.pdf) — _<description> — added by hand YYYY-MM-DD_.attachment-3stands for the saved filename,<id>-prefix included. When the document is a ticket file and a REQUIREMENTS file exists for it (its base with.TICKET→.REQUIREMENTS; for a-vNre-fetch with none, the ticket's latest), also append one line per asset — the same embed or link, its path relative to the REQUIREMENTS file when that sits in another directory, plus the caption — at the end of its Context part; no new section, nothing else changed. -
Report project-relative paths: the document, the REQUIREMENTS file when it got a line — its requirements predate the asset and may need re-refining — then one line per asset with its caption. When the document is a ticket file with no REQUIREMENTS file yet and
/refine-ticketis installed, hand off with one copy-pasteable launch command in the agent tool's syntax (e.g.claude --name refine-<slug> "/refine-ticket <document>"), then the alternative, the tool's clear command (e.g./clear) followed by/refine-ticket <document>.
Sources
Escape paths and URLs from user or ticket text in every command for the shell running it (POSIX
' → '\'', PowerShell ' → ''), and again for a nested language (AppleScript, PowerShell).
- Pasted image — the agent tool's paste cache, when it keeps one; e.g. Claude Code writes
~/.claude/image-cache/$CLAUDE_CODE_SESSION_ID/<N>.png,<N>the image's number in the session. No cache or no such file → the OS clipboard, see clipboard.md. Neither works → ask the user to save the image and paste its path. - Local path — copy the file.
- URL — HTTP(S) only, redirects included (
curl.exeon Windows):curl -fSL --proto '=http,https' --proto-redir '=http,https' -o '<file>' -- '<url>'; no auth flows here — on failure or a login page, ask the user to download the file and paste its path.
Signals
- GitHub stars
- 55
- Forks
- 11
- Last commit
- Sep 2026
Advanced
- Item type
- skill
- Key
attach-to-ticket- Source
- github.com/eai-org/agent-toolkit