keelapps/Satchel for Jira
For the issue with twelve attachments and no download button
Twelve attachments means twelve previews. Or one zip.
Jira Cloud has no “download all attachments” button. Satchel adds it — for one issue, for a JQL result, or for a whole project foldered by issue key — and then answers the question that always follows: what is actually in there, and how much of it can go? The archive is assembled in your own browser from your own Jira session, so attachment bytes never touch a server of ours. There is not one.
To get twelve attachments off a Jira issue you open a preview, close it, and do it eleven more times. Across issues, bulk download does not exist at all. The request has been open on Atlassian's own tracker since 2019 — JRACLOUD-72921, 121 votes, still Gathering Interest — and past 150 attachments Jira stops rendering them altogether (JRACLOUD-81747).
The Marketplace has a download-only app in this space and a heavyweight document management suite next to it. Nobody has put bulk download, attachment governance and storage analysis in one place.
What it does
One zip, however many files
Every attachment on an issue in a single archive, from a panel on the issue itself. It works past the 150 attachments Jira itself stops rendering.
A JQL result, or a project
From the project page: zip everything a JQL query matches, or the whole project,
foldered by ISSUE-KEY/. Progress and cancel throughout.
Nothing overwritten, nothing hidden
Two files with the same name are renamed inside the archive rather than silently overwriting each other, and a note inside the zip lists anything that could not be included, with the reason.
See where the storage went
Occupancy by uploader, file type, issue type and age, plus the biggest files. Jira shows one site-wide number and nothing underneath it.
Duplicate candidates
Files grouped by filename and exact byte size, with the bytes each group would reclaim. Candidates, not verdicts — Jira exposes no content hash, and Satchel says so wherever it shows a number.
Deletion that asks twice
A dry run, a typed confirmation, an audit record per file. It ships switched off and is administrator-only when enabled — because Jira has no recycle bin for attachments.
Reclaiming 40 GB, end to end
-
Scan the project
The project page builds an attachment inventory in the background: filename, size, type, uploader, issue and age for every file. It is checkpointed, so a big project finishes.
-
Read the reports
Storage by uploader and by file type, the biggest files, and the duplicate candidate groups with the bytes each would free. Export the whole inventory as CSV if somebody else has to approve the list.
-
Take a copy first
Zip what you are about to remove — the archive is built in your browser and lands on your disk, not on anybody's server — so “deleted” means “out of Jira”, not “gone”.
-
Delete, on the record
An administrator enables deletion, reads the dry run, types the confirmation, and Satchel records every file it removed and who removed it. That trail is deliberately not deletable from the interface.
Against what you have today
| Question | Native Jira | Download-only apps | Satchel |
|---|---|---|---|
| Download every attachment on an issue? | One preview at a time | Yes | One zip |
| Across a JQL result or a project? | — | Sometimes | Foldered by issue key |
| What is eating the storage? | One site-wide number | — | By uploader, type, age, size |
| Which files are duplicated? | — | — | Candidates, with reclaimable bytes |
| Delete in bulk, with a record? | One at a time, no trail | — | Dry run, confirmation, audit |
| Do the files pass through a vendor server? | — | Often | Never — built in your browser |
Limits we state up front
Duplicate detection finds candidates, not proven duplicates. Jira exposes no content hash for an attachment, and proving two files identical would mean downloading both — for a whole project, every byte in it. Satchel therefore matches on filename and exact byte size, and that qualification travels with the number in the payload, so no screen can show you reclaimable bytes without the sentence explaining what they are based on. Two files with the same name and different sizes are not grouped; neither are two unrelated files that happen to be the same size.
Deletion is irreversible. Jira has no recycle bin for attachments. A file deleted through Satchel is gone from Jira, and the only recovery is an Atlassian support restore of the entire site. Satchel requires a dry run and a typed confirmation and records every deletion, but it cannot undo one. Deletion ships switched off and is administrator-only when enabled.
One scope is broader than what the app does. Deleting an attachment
needs Jira's classic write:jira-work scope, whose consent text mentions
creating and editing issues, posting comments and deleting issues. Satchel does none
of those. It is the narrowest scope Atlassian currently offers that includes deleting
an attachment — the granular one that would say exactly that is still in Beta — and
an automated test fails the build if any code path reaches a mutating call other
than the single attachment delete.
Uploading attachments is deliberately not built. The app requests no scope for it and the interface has no path to it.
Availability
Satchel for Jira is built and deployed on Atlassian Forge. It is going through Atlassian Marketplace review; this page will link to the listing as soon as it is live.
Licensing is handled by Atlassian. Sites with 10 users or fewer pay nothing at all, and above that the single-issue zip and the direct download stay free forever on every install — the fix for JRACLOUD-72921 is never behind a licence check. What a licence buys is scale and governance: cross-issue archives, the project inventory, the duplicate and storage reports, CSV export and deletion.
There is a Satchel for Confluence too, with the same brand, the same zero-egress design, and bulk attachment move between pages.
Questions, bug reports and feature requests: raise a support request.
Found a security issue? Please report it privately rather than in a public channel.