Download All, lightbox navigation, and an MCP that finally sees attachments
Every attachment in one ZIP, an image preview with thumbnail rail and swipe on mobile, plus: the MCP actually finds files now. A build-in-public devlog.

Four changes around attachments in one session: Download All, a compact upload area, a rebuilt image preview with thumbnail rail and mobile swipe -- plus a fix so the MCP actually notices attachments exist. Classic build-in-public moment: one feature, three tangible side effects.
Download All: one ZIP for every attachment
When a ticket has several files -- screenshots, a PDF, an export log, a CSV -- the only option used to be clicking each one. From now on, there's a Download all button at the top of the attachments list.
What happens under the hood
- The API streams every non-deleted attachment from storage and packs them into a ZIP.
- Filenames are deduplicated: two
logs.txton the same ticket becomelogs.txtandlogs (1).txt. - Legacy attachments without an S3 key are skipped -- you see how many files ended up in the ZIP and how many were left out.
- Limit: 500 MB aggregate per ZIP. Above that the API politely refuses instead of OOMing.
- The endpoint is rate-limited (20 bulk downloads per hour) so nobody accidentally DoSes storage.
When the button appears
As soon as a ticket has two or more attachments. For a single attachment the ZIP detour isn't worth it.
Upload that gets out of the way
The old upload area always showed a big dashed zone at the top of the tab -- even if twenty files were already attached. The tab now behaves more adaptively:
- Empty ticket: full drop zone with icon, text and click target like before.
- Already has attachments: the zone shrinks to a slim one-liner above the list.
- The list itself is the drop target: drag a file anywhere over the attachment list and an overlay hint appears -- release and the upload starts.
Image preview: a lightbox that doesn't jump
The image preview used to have a problem: images brought their own natural size, the lightbox grew with them, and switching between portrait and landscape made the entire UI bounce around.
What's different now
- The lightbox window is fixed at 90vw × 90vh -- no matter how large the image, the frame stays put.
- The image itself scales via
object-containinside the available area. - Arrow buttons on either side, plus ← / → on the keyboard and Escape to close.
- Thumbnail rail on the right (below on mobile): a click on a thumbnail jumps directly there. The active preview is marked with a coloured border.
Mobile: swipe instead of arrow-hunt
Hitting arrows with your thumb was painful on small screens. On mobile:
- Thumbnails move below the image and scroll horizontally.
- Swipe left/right on the image to page to the next/previous screenshot.
- The image uses the full width because the thumbnail rail isn't eating sidebar space.
MCP: attachments are visible now
While building the download-all path, something came up during debugging: the MCP could load attachments (attachment://{attachmentId}), but didn't know they exist.
Specifically: neither the tickets_get tool nor the ticket://{id}/timeline resource returned attachment IDs. The timeline only had comments and PR events. Agents working via MCP -- Claude Desktop, a custom bot, a Spedy routine -- had a blind spot for files.
What changed
tickets_getnow returnsattachmentCountplus anattachmentsarray withid,uri,originalName,mimeType,size,uploadedByanduploadedAt. An agent can hand theuri(attachment://...) straight to the resource handler.ticket://{id}/timelinenow includes anattachment_uploadedevent per file, sorted inline with comments and user events. If you ask "what happened on this ticket lately?", uploads show up at the right point in time.- Permissions are unchanged: the board-level access check still runs, soft-deleted records are still hidden.
Turning an agent loose on Spedy ("summarise this ticket and look at the attached logs") no longer needs an extra call to discover attachments.
Build in public: why all of this together?
Traditional release notes cleanly separate "Feature X" and "Bugfix Y". In practice they're often entangled: while building a feature you notice the preview has a layout bug. In the feedback round a mobile issue joins in. While debugging you discover that the MCP has the same problem on a different layer.
We decided to surface that -- a feature plus what we picked up along the way. Instead of "Download All shipped" followed three weeks later by "MCP fix shipped", you get the how. Build in public for us means: no polished staging, just the work as it happens.
Next up
- Download progress for single files: bulk download has a clear start/end state; large single-file downloads are still missing a progress bar.
- Preview for more file types: images already open in a lightbox. PDF and Office previews are on the list.
- Pinch-zoom in the lightbox: swipe and thumbnails are in; zooming further into high-resolution screenshots is still open.
Frequently asked questions
Quick answers to the most common questions about this topic.
Where do I find the Download-All button?
Is there a size limit on the ZIP?
How do I navigate between images in the preview?
What was the MCP attachment bug?
attachment://{id}, but neither tickets_get nor the timeline resource returned attachment IDs. Agents literally didn't know files existed. Both endpoints now include them.What does 'build in public' mean for Spedy?
Keep reading

Epic Grouping, Bulk Actions in the Backlog, and Opus 4.7
Group stories under their Epics, act on many tickets at once in the backlog and Issues Hub, and use Claude Opus 4.7 as the new runner default.
Per-Job Cost Tracking – and Notifications That Finally Arrive
Runner jobs now show costs in real time. Teams can set budgets. Secret comments now correctly trigger notifications. And MCP users can finally access team projects.

MCP for Everyone, Cache Metrics & Job Notifications
MCP integration is now available on all plans, runner jobs display cache token metrics, and notifications keep you informed when jobs complete, fail, or need input.