File Attachments Guide
TokST enables you to attach files to memories, providing rich context alongside text. Files are stored in Cloudflare R2 with metadata indexed in Supabase.
Overview
When you attach a file to a memory, TokST:
- Uploads the file to Cloudflare R2 object storage
- Stores metadata (filename, size, MIME type, URL) in Supabase
- Associates the attachment with the memory
- Generates a presigned upload URL (valid for 1 hour) and presigned download URLs (valid for 15 minutes)
This means files are never stored in the database directly — they live in R2, keeping your database lean and fast.
CLI Usage
Attach During Creation
Use the --file flag when storing a new memory. The flag is repeatable for multiple files.
# Single file
tokst remember "Sprint retrospective notes" --file retro-notes.md
# Multiple files
tokst remember "Q3 planning documents" --file roadmap.pdf --file budget.xlsx --file timeline.png
The CLI accepts local files. For a remote URL, use the remote MCP fileUrl input or download the file locally before passing --file.
Attach to an Existing Memory
Use the attach subcommand:
tokst memory attach <memory-id> --file document.pdf
Download Attachments
Pull a memory's files back to your local machine with the download subcommand. Files are streamed from R2 via a presigned GET URL and saved with their original filenames.
# Download all attachments to ~/Downloads
tokst memory download <memory-id>
# Specify an output directory (auto-created if missing, ~ expands to $HOME)
tokst memory download <memory-id> --out ./files
# Download a single attachment by ID
tokst memory download <memory-id> --attachment-id <attachment-id>
# Machine-readable output
tokst memory download <memory-id> --json
Download is cloud-only. Local SQLite mode throws — run
tokst login --key <api-key>first.
MCP Usage
When using the MCP server, pass file parameters in the tool call:
{
"content": "Meeting notes with attached diagram",
"filePath": "/home/user/diagram.png"
}
Or with a remote URL:
{
"content": "Reference architecture",
"fileUrl": "https://example.com/architecture.png"
}
To attach a file to an existing memory via MCP, use tokst_attach_file:
{
"memoryId": "mem_abc123",
"fileUrl": "https://example.com/report.pdf",
"filename": "report.pdf"
}
ChatGPT uploads are bound automatically through the tool's openai/fileParams metadata. To download the file again, call tokst_download_file:
{
"memoryId": "mem_abc123",
"attachmentId": "attachment-uuid"
}
The remote MCP server returns a 15-minute signed URL as both JSON and MCP resource_link content. Remote MCP uploads have a 50 MB per-file limit.
Upload Confirmation
An attachment stays pending until confirmation. The confirmation route performs an R2 HEAD request, rejects missing or empty objects with 409, and records the actual object size and MIME type before changing the attachment to active. Pending or failed uploads older than two hours are cleaned up automatically.
Web Dashboard
The web dashboard provides a drag-and-drop interface for file uploads with real-time progress indicators. Navigate to any memory and use the attachment panel to upload files.
Storage Quotas
Plans have the following storage limits for file attachments:
| Plan | Storage Quota |
|---|---|
| Free | 500 MB |
| Starter | 2 GB |
| Pro | 10 GB |
| Team workspace | 20 GB shared |
| Legacy Max / Team | Existing entitlement |
| Upload Channel | Per-file Behavior |
|---|---|
| Web dashboard | 500 MB client-side maximum |
| Remote MCP | 50 MB maximum |
| CLI | Limited by the account's remaining storage quota |
Storage usage is tracked in real time and visible through tokst status.
R2 Path Structure
Files are stored in Cloudflare R2 using the following path convention:
{workspace_id}/{atlas_id}/{memory_id}/{attachment_id}-{filename}
For example:
ws_abc123/atlas_def456/mem_789abc/att_xyz789-report.pdf
This structure ensures:
- Isolation — Files from different workspaces never collide
- Discoverability — You can reconstruct paths from database metadata
- Cleanup — Deleting a memory or atlas removes the matching R2 objects before database cleanup
Security
File access is secured with presigned URLs:
| Action | URL Validity |
|---|---|
| Upload | 1 hour |
| Download | 15 minutes |
Presigned URLs are generated server-side and require valid authentication. Direct R2 bucket access is blocked. This ensures that only authenticated users with appropriate permissions can upload or download files.
Object deletion accepts only an exact internal service credential or a user token with matching attachment ownership. User-provided file keys outside the authenticated scope are rejected.
Best Practices
- Use meaningful filenames — The filename becomes part of the R2 path and is displayed in the dashboard
- Keep files under 100 MB for faster uploads
- Use remote MCP
fileUrlwhen an agent needs to attach a public remote asset - Monitor your quota with
tokst statusto avoid hitting storage limits