Handles all file operations in Butterbase apps through a single manage_storage tool with five actions: upload_url, download_url, list, delete, and update_config. The mental model is clean: you store object_id UUIDs in your tables (users.avatar_id, posts.image_id), never the s3_key, and generate fresh presigned URLs on demand since they expire in an hour. Upload is a three-step dance: request a URL, PUT the file to S3 with matching Content-Type, then persist the object_id or you've orphaned it. Access control is hardcoded to owner-or-public with an optional app-wide publicReadEnabled flag. No custom RLS on storage_objects, so if you need workspace-level permissions or similar, wrap downloads in a serverless function that checks your own tables first.
- GitHub stars
- 532
- last updated
- Jun 11, 2026
Install
$ npx -y skills add butterbase-ai/butterbase-skills --skill storage --agent claude-codeInstalls into .claude/skills of the current project.
Files
Butterbase Storage
Butterbase stores files in S3 (or LocalStack in dev) and exposes them via presigned URLs. Every file gets a stable object_id (UUID) that you persist in your tables; URLs are generated on demand and expire.
All storage operations go through one tool: manage_storage with an action parameter.
| Action | Purpose |
|---|---|
upload_url | Generate a 15-minute presigned PUT URL and reserve an object_id |
download_url | Generate a 1-hour presigned GET URL for a stored object |
list | List objects (scoped by caller's role) |
delete | Permanently remove an object from S3 + database |
update_config | Toggle app-level publicReadEnabled and other storage settings |
1. The mental model: object_id vs s3_key
| Field | What it is | When you use it |
|---|---|---|
object_id | UUID, stable, app-level handle | Persist in your tables (e.g. users.avatar_id, posts.image_id) |
s3_key | Internal bucket path like app_abc/user_uuid/file.jpg | Internal only — never treat this as a URL |
Sponsors
Details
- Repository
- github.com/butterbase-ai/butterbase-skills
- License
- MIT
- First seen
- Jun 11, 2026
