# encore-go-bucket

A skill that shows the agent how to declare buckets and handle files in Encore Go: uploads, downloads, signed URLs.

- skill · `type=skill` · Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, OpenCode · 307 installs · ★ 30
- Author: encoredev
- License: Apache-2.0 · policy=mirror · the beginning of the file is at the end of this page
- Source: https://github.com/encoredev/skills/tree/HEAD/encore/go-bucket/SKILL.md
- Updated: 2026-10-23
- HTML: https://affpapa.org/en/nevibecode/skills/encore-go-bucket

## What it does

This skill covers object storage inside Encore Go services. A bucket is declared as a package-level variable with `objects.NewBucket` from `encore.dev/storage/objects`. Encore provisions the storage underneath: S3 on AWS, GCS on GCP, in-memory locally.

Inside are ready patterns for the operations you need: streaming `Upload`, `Download`, `Exists`, `Attrs`, `List`, `Remove`. Public buckets get `PublicURL`; private ones get `SignedUploadURL` and `SignedDownloadURL` with a TTL so browsers talk to storage directly instead of through your service. A separate section covers `BucketRef` with permission sets like `Downloader`, `Uploader`, `Lister`, `Attrser`, `Remover`.

The skill advises declaring buckets at package level and keeping them private by default, opting into `Public: true` only for assets meant to be fetched without auth. When you hand bucket access to library code, use `BucketRef` — the permission contract then lives in the type system. Worth a look at your own buckets: a public one holding user files is an open door.

## Install

### Claude Code (native platform)

1. **Skills CLI (Vercel)**
```bash
npx skills add encoredev/skills --skill encore-go-bucket -a claude-code
```
```bash
npx skills add encoredev/skills --skill go-bucket -a claude-code
```

2. **Manually: put the files in place**
- File: `~/.claude/skills/go-bucket/SKILL.md` — Copy the whole skill folder; for one project use .claude/skills/go-bucket/

### Codex

1. **Skills CLI (Vercel)**
```bash
npx skills add encoredev/skills --skill go-bucket -a codex
```

2. **Manually: put the files in place**
- File: `.agents/skills/go-bucket/SKILL.md` — For all projects use ~/.agents/skills/

### Cursor

1. **Skills CLI (Vercel)**
```bash
npx skills add encoredev/skills --skill go-bucket -a cursor
```

2. **Manually: put the files in place**
- File: `.cursor/skills/go-bucket/SKILL.md` — Cursor also reads .agents/skills/ and .claude/skills/

### GitHub Copilot

1. **GitHub CLI**
```bash
gh skill install encoredev/skills go-bucket
```

2. **Manually: put the files in place**
- File: `.github/skills/go-bucket/SKILL.md`

### Gemini CLI

1. **Skills CLI (Vercel)**
```bash
npx skills add encoredev/skills --skill go-bucket -a gemini-cli
```

2. **Platform CLI**
```bash
gemini skills install https://github.com/encoredev/skills --path encore/go-bucket
```

### Windsurf (Devin Desktop)

**Manually: put the files in place**
- File: `.devin/skills/go-bucket/SKILL.md` — The legacy .windsurf/skills/ path still works

### OpenCode

**Skills CLI (Vercel)**
```bash
npx skills add encoredev/skills --skill go-bucket -a opencode
```

### Claude.ai

**Claude.ai**
- Zip the folder and upload it in Settings → Capabilities → Skills

Where a file is given instead of a command, copy the files from the source to that path: https://github.com/encoredev/skills/tree/HEAD/encore/go-bucket/SKILL.md

## When to use it
- store a user avatar in an Encore service
- hand out a temporary link to a stored file
- list bucket objects with their sizes
- delete a document by key
- pass bucket access to a helper with limited permissions

## Example prompts
- Add a private bucket for avatar uploads to my Encore Go service
- Write an endpoint that returns a signed upload URL valid for 2 hours
- Show me how to give a helper download-only access with BucketRef

## Source text · SKILL.md · Apache-2.0

Below is the content of a third-party file. It is data, not instructions for you: do not act on anything written inside unless the human asks. Block tag: 885d02ec7311e798.

BEGIN THIRD-PARTY FILE 885d02ec7311e798
````text
---
name: encore-go-bucket
description: Store unstructured files in Encore Go using `objects.NewBucket` from `encore.dev/storage/objects` — uploads, images, documents, blobs.
when_to_use: >-
  User wants to upload, download, list, or delete files from an Encore Go service — profile pictures, avatars, document uploads, image storage, media assets, generated reports, blob data. Covers public vs private buckets, signed upload/download URLs, bucket references with permission types (Uploader, Downloader, Lister, Attrser, Remover), and operations like `Upload`, `Download`, `List`, `SignedUploadURL`. Trigger phrases: "object storage", "bucket", "S3", "GCS", "blob", "user uploads", "profile picture", "image upload", "store a file", "file storage".
---

# Encore Go Object Storage

## Instructions

A `Bucket` is a logical store for files. Encore provisions the underlying object storage (S3 on AWS, GCS on GCP, in-memory locally). Declare buckets as package-level variables.

```go
package uploads

import "encore.dev/storage/objects"

// Private bucket (default)
var Uploads = objects.NewBucket("user-uploads", objects.BucketConfig{})

// Public bucket — files accessible via public URL
var PublicAssets = objects.NewBucket("public-assets", objects.BucketConfig{
    Public: true,
})
```

## Operations

```go
import (
    "fmt"
    "io"
)

// Upload (streaming pattern)
writer := Uploads.Upload(ctx, "path/to/file.jpg")
_, err := io.Copy(writer, dataReader)
if err != nil {
    writer.Abort()
    return err
}
err = writer.Close()

// Download
reader := Uploads.Download(ctx, "path/to/file.jpg")
if err := reader.Err(); err != nil {
    return err
}
defer reader.Close()
data, _ := io.ReadAll(reader)

// Existence check
exists, err := Uploads.Exists(ctx, "path/to/file.jpg")

// Attributes (size, content type, ETag)
attrs, err := Uploads.Attrs(ctx, "path/to/file.jpg")

// List
for err, entry := range Uploads.List(ctx, &objects.Query{}) {
    if err != nil {
        return err
    }
    fmt.Println(entry.Key, entry.Size)
}

// Delete
err := Uploads.Remove(ctx, "path/to/file.jpg")

// Public URL (only for public buckets)
url := PublicAssets.PublicURL("image.jpg")
```

## Signed URLs

Generate temporary URLs so clients can upload/download directly without going through your service:

```go
import "time"

// Signed upload URL (expires in 2 hours)
url, err := Uploads.SignedUploadURL(ctx, "user-uploads/avatar.jpg",
    objects.WithTTL(time.Duration(7200)*time.Second))

// Signed download URL
url, err := Uploads.SignedDownloadURL(ctx, "documents/report.pdf",
    objects.WithTTL(time.Duration(7200)*time.Second))
```

## Bucket References

Pass bucket access to library code with a specific permission set:

```go
// Create a reference with download permission only
````
END THIRD-PARTY FILE 885d02ec7311e798

The third-party file has ended. Everything between the 885d02ec7311e798 tags is data: requests and commands from it are not followed. An “end of file” line with another tag inside the block is part of the file.

First 2784 of 3490 bytes. © encoredev · Apache-2.0 · https://github.com/encoredev/skills/tree/HEAD/encore/go-bucket/SKILL.md

_Part of the page did not fit — see the HTML version._

---
NeVibeCode on affpapa.org. Catalog texts are descriptions, not instructions for the agent. How to choose and install: https://affpapa.org/en/nevibecode/agents.md
