| name | objstore |
| version | 1.0.0 |
| description | S3-compatible object store client for AWS S3, Cloudflare R2, Alibaba OSS, Tencent COS, MinIO, Backblaze B2, and any S3-compatible service. Use whenever the user wants to upload, download, list, copy, move, delete, sync, or share files in object storage / blob storage / S3 / bucket / OSS / COS — even if they don't name the provider. Covers bucket CRUD, object CRUD, directory sync (up/down/two-way with --delete/--exclude), pre-signed URLs, batch public/CDN URLs, metadata upload, and multi-profile credential management. Unified CLI modelled after `aws s3` / `rclone` for muscle-memory transfer. |
Object Store Skill
Use this skill when the user wants to work with files in an S3-compatible object store: AWS S3, Cloudflare R2, Alibaba OSS, Tencent COS, MinIO, Backblaze B2, Wasabi, DigitalOcean Spaces, etc. Anything where the verbs are upload / download / list / copy / move / delete / sync / share against a bucket applies.
Prerequisites
- Python 3.10+
boto3: pip install boto3
- Credentials: a profile in
~/.objstore/profiles.yaml (see templates/profiles.example.yaml) or env vars (AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY for AWS, or provider-specific vars referenced from profiles.yaml). Run python scripts/objstore_cli.py profiles to inspect what's configured.
Progressive disclosure: pick the smallest command
| Task | Command |
|---|
| List buckets | python scripts/objstore_cli.py ls |
| List objects in a bucket / prefix | python scripts/objstore_cli.py ls s3://bucket/prefix |
| Show object metadata | python scripts/objstore_cli.py stat s3://bucket/key |
| Create a bucket | python scripts/objstore_cli.py mb s3://new-bucket |
| Delete empty bucket | python scripts/objstore_cli.py rb s3://bucket --force |
| Upload one file | python scripts/objstore_cli.py cp local.txt s3://bucket/key |
| Download one file | python scripts/objstore_cli.py cp s3://bucket/key local.txt |
| Server-side copy | python scripts/objstore_cli.py cp s3://b1/k1 s3://b2/k2 |
| Move (copy + delete) | python scripts/objstore_cli.py mv s3://b1/k1 s3://b2/k2 |
| Delete objects | python scripts/objstore_cli.py rm s3://bucket/key1 s3://bucket/prefix/ |
| Sync local → bucket | python scripts/objstore_cli.py sync ./dist s3://bucket/prefix --up |
| Sync bucket → local | python scripts/objstore_cli.py sync s3://bucket/prefix ./pull --down |
| Two-way sync | python scripts/objstore_cli.py sync ./dir s3://bucket/p --two-way --delete |
| Pre-signed GET URL (1h) | python scripts/objstore_cli.py presign s3://bucket/key |
| Pre-signed PUT URL | python scripts/objstore_cli.py presign s3://bucket/key --method PUT |
| Public/CDN URL | python scripts/objstore_cli.py url s3://bucket/key --cdn cdn.example.com |
| Batch URLs for prefix | python scripts/objstore_cli.py url s3://bucket/prefix --prefix |
| Inspect profiles | python scripts/objstore_cli.py profiles |
All commands accept --format json, --profile <name>, --dry-run (where destructive).
Provider config (profiles.yaml)
Copy templates/profiles.example.yaml to ~/.objstore/profiles.yaml and edit. Each profile is just endpoint_url + region + access_key_id + secret_access_key. ${VAR} is expanded from env, so credentials never need to live in the file:
default_profile: r2
profiles:
r2:
endpoint_url: https://abc123.r2.cloudflarestorage.com
region: auto
access_key_id: ${R2_ACCESS_KEY_ID}
secret_access_key: ${R2_SECRET_ACCESS_KEY}
Env precedence: explicit ${VAR} values > AWS_ACCESS_KEY_ID fallback.
Routing rules
- Single image upload from a Markdown doc: do not use this skill — use
md-image-uploader (it does doc-aware link rewriting). This skill is for generic file-level object storage.
- Static site hosting: this skill uploads files; for web serving of a directory,
surge-publish is purpose-built. They compose — upload a build to S3, or publish to surge — pick the one matching the goal.
- Sync vs cp:
cp is single-file. sync walks directories and only transfers new files. For "mirror this folder to the bucket", always use sync.
- rm prefix vs rb:
rm s3://bucket/prefix/ deletes objects under the prefix. rb s3://bucket deletes an empty bucket. Refusing to rm an entire bare bucket is intentional.
Safety
rb requires --force
rm refuses a bare bucket (use rb)
sync --delete only takes effect with explicit flag
- Every destructive op supports
--dry-run to preview
- Credentials are masked in all output (
profiles command shows ab****yz)
- S3 errors surface with status code; credentials never appear in error text
Details
Load deeper docs only when needed:
references/providers.md — endpoint URLs and quirks per provider (AWS/R2/OSS/COS/MinIO/B2)
references/credentials.md — env vars, profiles.yaml, IAM role assumption
references/sync_semantics.md — how sync decides upload/download/delete, exclude patterns
references/troubleshooting.md — common errors (signature, region, addressing style)