Attachments¶
Four verbs under jira issue attachment: add to upload, list to find the
ids Jira assigns, then download and delete to act on one file by that id.
Use it for logs, screenshots, and exports — the binary evidence that doesn't
belong in a comment. JSON examples below show the data block only; the
envelope wrapper and exit codes live on Output.
attachment add¶
Upload one or more local files to one or more issues. Pass paths positionally
for a quick upload, or use repeated --file flags when a path holds
shell-sensitive characters (a comma, a space). add takes KEY..., so the
same files fan out to every issue you name; add -p / --parallelism to upload
to several issues at once.
jira issue attachment add PROJ-123 ./screenshot.png
jira issue attachment add PROJ-123 --file ./report,final.pdf --file ./logs.txt
jira issue attachment add PROJ-1..10 -p 4 --file ./release-notes.md
jira issue attachment add PROJ-123 ./report.pdf --dry-run
- Each
--fileis exactly one path — unlike a comma-separated list, it won't splitreport,final.pdfinto two bogus filenames. - Same file, every issue in the range, four uploads in flight at a time.
Every path is checked for existence, regular-file type, and size before any
HTTP call. --dry-run runs only that local preflight and uploads nothing — the
data carries dry_run: true and a files array of { path, size,
mime_inferred } instead of the uploaded attachments.
A successful upload returns the stored attachments, each with the id you'll need later:
{
"key": "PROJ-123",
"dry_run": false,
"attachments": [
{
"id": "10500",
"filename": "screenshot.png",
"mime_type": "image/png",
"size": 4096,
"created": "2026-06-01T22:00:29.281-0400",
"author": { "account_id": "712020:…", "display_name": "John Doe" }
}
]
}
100 MB cap
Each file — and the running total of a multi-file upload — must stay under 100 MB, or the command fails validation before contacting Jira. Your tenant may also enforce a smaller server-side limit.
attachment list¶
List what's attached to an issue and, crucially, the numeric ids Jira assigns —
you need one before you can download or delete. It accepts KEY... (lists
and PROJ-1..10 ranges); a single key returns data.attachments, multiple keys
return ordered data.results[], each entry carrying that issue's attachments
and pagination.
jira issue attachment list PROJ-123
jira issue attachment list PROJ-123 --all
jira issue attachment list PROJ-1..10 -p 4 --output=json
--limit (default 50) is applied client-side — Jira returns attachments as
part of the issue, so there's no server page to fetch. --all returns every
attachment regardless of --limit. Each row matches the attachment shape shown
under add; the pagination block rides in meta.pagination
with total always known and isLast: false signalling a truncated window
(re-run with --all — there is no cursor for a client-side window):
{
"data": {
"attachments": [ { "id": "10500", "filename": "screenshot.png", "…": "…" } ]
},
"meta": {
"pagination": { "startAt": 0, "maxResults": 50, "total": 2, "isLast": true }
}
}
attachment download¶
Fetch one attachment by id and write it to a file. This is single-target — it
takes KEY ATTACHMENT_ID, not a key list — because the id identifies exactly
one file. Binary content is always written to a file, never stdout, so a
JSON or compact consumer never has bytes spliced into its stream.
jira issue attachment download PROJ-123 10500
jira issue attachment download PROJ-123 10500 --to ./report.pdf --force
jira issue attachment download PROJ-123 10500 --to ./report.pdf --dry-run
Without --to, the file lands in the current directory under the server-supplied
filename (falling back to attachment-<id> if the response omits one). With
--to PATH it writes exactly there. Either way an existing target is protected:
the command fails unless you pass --force to overwrite. --dry-run validates
the target path and prints the planned write — data.mode and data.target —
without contacting Jira. A live download returns written_to and the bytes
count.
attachment delete¶
Remove one attachment by id. Like download this is single-target
(KEY ATTACHMENT_ID); run list first to find the id.
jira issue attachment delete PROJ-123 10500 --dry-run
jira issue attachment delete PROJ-123 10500 --force
--dry-run previews the deletion and never contacts Jira. Because the delete is
destructive, a live run needs confirmation: in headless, agent, or --no-input
mode it requires --force, and an interactive terminal prompts before deleting
when --force is omitted. Success returns { "attachment_id": "10500",
"deleted": true }.
See also¶
- Reading issues —
viewshows the attachment count on an issue - Output — the JSON envelope and exit codes
- Commenting — the other place files and context get attached