Skip to content

Attachments

Cards support file attachments. Upload from the card detail panel, or attach a URL. Attachments can optionally be scoped to a specific comment.

Storage drivers

Attachment bytes go to a pluggable StorageDriver, chosen with ATTACHMENT_STORAGE (see Configuration):

  • local (default, zero-config): the api proxies upload/download bytes and stores them on disk under ATTACHMENT_LOCAL_PATH. No external dependency — ideal for self-hosting a single host. Compose persists the bytes in a volume.
  • s3 (production): any S3-compatible backend (AWS S3, MinIO, R2, …). The api issues presigned PUT/GET URLs, so bytes never transit the api; downloads 302-redirect to a short-TTL signed URL.

The driver is transparent to clients — the same endpoints and the same MCP card_write { method: "attach_url" } work regardless.

Limits

Server-side limits are enforced on every surface (REST, MCP, URL ingestion), regardless of driver:

  • per-attachment sizeATTACHMENT_MAX_BYTES (default 25 MiB)
  • per-card countATTACHMENT_MAX_PER_CARD (default 20)
  • content-type allowlistATTACHMENT_CONTENT_TYPES (default: images, PDF, text/CSV, common office docs, zip)
  • aggregate quotas — per board and global byte caps

Upload lifecycle

A direct file upload is a two-step, confirmed flow: the client creates a pending attachment (reserving its declared size against the quota), uploads the bytes, then confirms it. Unconfirmed uploads are swept and deleted after ATTACHMENT_PENDING_TTL_SECONDS. A confirmed upload appends a card.attachment_added activity (payload { cardId, attachmentId, filename, contentType, sizeBytes }); deletion appends card.attachment_removed. Comment-scoped attachments carry the commentId, and deleting the comment removes its attachments.

Attaching a URL (agents)

An agent can attach an external URL directly:

jsonc
// MCP
card_write { "method": "attach_url", "params": { "cardId": "…", "url": "https://…" } }

URL attachments go through the same SSRF guard as webhooks and require https.

Released under the AGPL-3.0 license.