Token导航 LogoToken导航TokenDH.com
研究检索需要联网github未标认证来源可访问clear审计通过

supabase-storageSupabase storage 搜索

Agent Skill

supabase-storage 用于记录任务执行中的错误、用户纠正、经验和能力缺口,适合在 Codex、Claude、Cursor、Gemini CLI 中希望让 Agent 持续沉淀问题、修正和最佳实践时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

总安装

233

周安装

10

GitHub Stars

6

下载量

82
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

3

许可证

MIT

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:supabase-storage(Supabase storage 搜索)
来源仓库:https://github.com/raudbjorn/claude
仓库路径:skills/supabase-storage
安装命令:
npx skills add https://github.com/raudbjorn/claude --skill supabase-storage
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。不同来源提供的安装方式可能略有差异;本站展示可直接复制的安装命令,安装前请核对来源页面。

skills.shnpx skills
npx skills add https://github.com/raudbjorn/claude --skill supabase-storage

简介

这项全面的 Supabase 存储技能涵盖:

  • 存储桶管理 - 创建、配置和管理存储桶
  • 文件操作 - 上传、下载、列出、移动、复制和删除文件
  • URL 生成 - 公共 URL、签名 URL 和签名上传 URL
  • RLS 策略 - 全面的访问控制模式
  • 辅助函数 - 用于路径和扩展名操作的 SQL 实用程序
  • 边缘功能集成-高级门禁场景
  • 最佳实践 - 安全性、性能和组织指南
  • 图像转换 - 内置图像处理
  • 使用 Supabase Storage 时请使用此技能,以确保最佳实践、安全性和最佳性能。
  • 每周安装量
  • 10
  • 存储库
  • 劳德比约恩/克劳德
  • GitHub 之星
  • 6
  • 第一次看到
  • 2026 年 1 月 23 日
  • 安全审计
  • Gen Agent Trust Hub 通行证
  • 套接字通行证
  • 斯尼克通行证

SKILL.md

Supabase Storage Expert

You are an expert in Supabase Storage, specializing in file management, bucket configuration, access control, and Row Level Security (RLS) policies for storage objects.

1. Storage Architecture Overview

Supabase Storage provides S3-compatible object storage with built-in CDN, image transformations, and Row Level Security integration.

Key Components:

  • Buckets: Containers for organizing files (public or private)
  • Objects: Files stored within buckets
  • RLS Policies: Security rules controlling access to buckets and objects
  • Helper Functions: SQL functions for path manipulation and access control

2. Bucket Management

Creating Buckets

JavaScript

const { data, error } = await supabase.storage.createBucket('avatars', {
  public: true,
  allowedMimeTypes: ['image/*'],
  fileSizeLimit: '1MB',
})

SQL

insert into storage.buckets (id, name, public)
values ('avatars', 'avatars', true);

Config.toml (Local Development)

[storage.buckets.images]
public = false
file_size_limit = "50MiB"
allowed_mime_types = ["image/png", "image/jpeg"]
objects_path = "./images"

Bucket Operations

Get Bucket:

const { data, error } = await supabase.storage.getBucket('avatars')

List Buckets:

const { data, error } = await supabase.storage.listBuckets()

Update Bucket:

const { data, error } = await supabase.storage.updateBucket('avatars', {
  public: false,
  allowedMimeTypes: ['image/png', 'image/jpeg'],
  fileSizeLimit: '5MB'
})

Delete Bucket:

const { data, error } = await supabase.storage.deleteBucket('avatars')

Empty Bucket:

const { data, error } = await supabase.storage.emptyBucket('avatars')

3. File Operations

Upload Files

Standard Upload

const avatarFile = event.target.files[0]
const { data, error } = await supabase
  .storage
  .from('avatars')
  .upload('public/avatar1.png', avatarFile, {
    cacheControl: '3600',
    upsert: false
  })

Upload from Base64 (React Native)

import { decode } from 'base64-arraybuffer'

const { data, error } = await supabase
  .storage
  .from('avatars')
  .upload('public/avatar1.png', decode('base64FileData'), {
    contentType: 'image/png'
  })

TypeScript Upload Function

async function uploadAvatar(file: File, userId: string) {
  const fileExt = file.name.split('.').pop()
  const fileName = `${userId}-${Math.random()}.${fileExt}`
  const filePath = `avatars/${fileName}`

  const { data, error } = await supabase.storage
    .from('avatars')
    .upload(filePath, file, {
      cacheControl: '3600',
      upsert: false,
    })

  if (error) {
    throw new Error(`Upload failed: ${error.message}`)
  }

  // Get public URL
  const { data: urlData } = supabase.storage
    .from('avatars')
    .getPublicUrl(filePath)

  console.log('File uploaded to:', urlData.publicUrl)
  return { path: data.path, url: urlData.publicUrl }
}

Resumable Uploads

Using tus-js-client

const tus = require('tus-js-client')

async function uploadFile(bucketName, fileName, file) {
  const { data: { session } } = await supabase.auth.getSession()

  return new Promise((resolve, reject) => {
    var upload = new tus.Upload(file, {
      endpoint: `https://${projectId}.storage.supabase.co/storage/v1/upload/resumable`,
      retryDelays: [0, 3000, 5000, 10000, 20000],
      headers: {
        authorization: `Bearer ${session.access_token}`,
        'x-upsert': 'true'
      },
      uploadDataDuringCreation: true,
      removeFingerprintOnSuccess: true,
      metadata: {
        bucketName: bucketName,
        objectName: fileName,
        contentType: 'image/png',
        cacheControl: 3600
      },
      chunkSize: 6 * 1024 * 1024, // Must be 6MB
      onError: function (error) {
        reject(error)
      },
      onProgress: function (bytesUploaded, bytesTotal) {
        var percentage = ((bytesUploaded / bytesTotal) * 100).toFixed(2)
        console.log(percentage + '%')
      },
      onSuccess: function () {
        resolve()
      }
    })

    return upload.findPreviousUploads().then(function (previousUploads) {
      if (previousUploads.length) {
        upload.resumeFromPreviousUpload(previousUploads[0])
      }
      upload.start()
    })
  })
}

Using Uppy.js

import { Uppy, Dashboard, Tus } from 'https://releases.transloadit.com/uppy/v3.6.1/uppy.min.mjs'

const token = 'anon-key'
const projectId = 'your-project-ref'
const bucketName = 'avatars'
const supabaseUploadURL = `https://${projectId}.supabase.co/storage/v1/upload/resumable`

var uppy = new Uppy()
  .use(Dashboard, {
    inline: true,
    target: '#drag-drop-area',
    showProgressDetails: true,
  })
  .use(Tus, {
    endpoint: supabaseUploadURL,
    headers: {
      authorization: `Bearer ${token}`,
    },
    chunkSize: 6 * 1024 * 1024,
    allowedMetaFields: ['bucketName', 'objectName', 'contentType', 'cacheControl'],
  })

uppy.on('file-added', (file) => {
  file.meta = {
    ...file.meta,
    bucketName: bucketName,
    objectName: `folder/${file.name}`,
    contentType: file.type,
  }
})

uppy.on('complete', (result) => {
  console.log('Upload complete!', result.successful)
})

Download Files

const { data, error } = await supabase
  .storage
  .from('avatars')
  .download('folder/avatar1.png')

With Transformations:

const { data, error } = await supabase
  .storage
  .from('avatars')
  .download('folder/avatar1.png', {
    transform: {
      width: 100,
      height: 100,
      quality: 80
    }
  })

List Files

const { data, error } = await supabase
  .storage
  .from('avatars')
  .list('folder', {
    limit: 100,
    offset: 0,
    sortBy: { column: 'name', order: 'asc' }
  })

Update/Replace File

const { data, error } = await supabase
  .storage
  .from('avatars')
  .update('folder/avatar1.png', newFile, {
    cacheControl: '3600',
    upsert: true
  })

Move File

const { data, error } = await supabase
  .storage
  .from('avatars')
  .move('folder/avatar1.png', 'folder/avatar2.png')

Copy File

const { data, error } = await supabase
  .storage
  .from('avatars')
  .copy('folder/avatar1.png', 'folder/avatar1-copy.png')

Remove Files

const { data, error } = await supabase
  .storage
  .from('avatars')
  .remove(['folder/avatar1.png', 'folder/avatar2.png'])

4. URL Generation

Public URLs

For Public Buckets:

const { data } = supabase
  .storage
  .from('public-bucket')
  .getPublicUrl('folder/avatar1.png')

console.log(data.publicUrl)

Direct URL Format:

https://[project_id].supabase.co/storage/v1/object/public/[bucket]/[asset-name]

Force Download:

https://[project_id].supabase.co/storage/v1/object/public/[bucket]/[asset-name]?download
https://[project_id].supabase.co/storage/v1/object/public/[bucket]/[asset-name]?download=customname.jpg

With Transformations:

const { data } = supabase
  .storage
  .from('public-bucket')
  .getPublicUrl('folder/avatar1.png', {
    transform: {
      width: 100,
      height: 100,
    }
  })

Signed URLs (Private Buckets)

Create Single Signed URL:

const { data, error } = await supabase
  .storage
  .from('avatars')
  .createSignedUrl('folder/avatar1.png', 60) // 60 seconds

TypeScript Function:

async function createSignedUrl(filePath: string, expiresIn: number = 3600) {
  const { data, error } = await supabase.storage
    .from('private-files')
    .createSignedUrl(filePath, expiresIn)

  if (error) {
    throw new Error(`Signed URL creation failed: ${error.message}`)
  }

  console.log('Signed URL:', data.signedUrl)
  return data.signedUrl
}

With Transformations:

const { data, error } = await supabase
  .storage
  .from('avatars')
  .createSignedUrl('folder/avatar1.png', 60, {
    transform: {
      width: 100,
      height: 100,
    }
  })

Force Download:

const { data } = await supabase
  .storage
  .from('avatars')
  .createSignedUrl('folder/avatar1.png', 60, {
    download: true,
  })

Create Multiple Signed URLs:

const { data, error } = await supabase
  .storage
  .from('avatars')
  .createSignedUrls(['folder/avatar1.png', 'folder/avatar2.png'], 60)

Signed Upload URLs

// Create a signed upload url
const filePath = 'users.txt'
const { token } = await supabase
  .storage
  .from(bucketName)
  .createSignedUploadUrl(filePath)

// Upload to the signed URL
await supabase
  .storage
  .from(bucketName)
  .uploadToSignedUrl(filePath, token, file)

5. Row Level Security (RLS) Policies

Basic Policy Structure

RLS policies control access to storage objects through the storage.objects table.

Required Permissions:

  • buckets table permissions: Varies by operation
  • objects table permissions: Varies by operation (select, insert, update, delete)

Public Bucket Policies

Allow Public Viewing:

create policy "Avatar images are publicly accessible"
  on storage.objects for select
  using (bucket_id = 'avatars');

Allow Authenticated Uploads:

create policy "Anyone can upload an avatar"
  on storage.objects for insert
  with check (
    bucket_id = 'avatars'
    AND auth.role() = 'authenticated'
  );

User-Specific Updates:

create policy "Users can update own avatar"
  on storage.objects for update
  using (
    auth.uid()::text = (storage.foldername(name))[1]
    AND bucket_id = 'avatars'
  );

User-Specific Deletes:

create policy "Users can delete own avatar"
  on storage.objects for delete
  using (
    auth.uid()::text = (storage.foldername(name))[1]
    AND bucket_id = 'avatars'
  );

Private Bucket Policies

User-Only Access:

-- Private bucket
insert into storage.buckets (id, name, public)
values ('private-files', 'private-files', false);

-- Users can only access their own private files
create policy "Users can access own private files"
  on storage.objects for select
  using (
    bucket_id = 'private-files'
    AND auth.uid()::text = (storage.foldername(name))[1]
  );

create policy "Users can upload own private files"
  on storage.objects for insert
  with check (
    bucket_id = 'private-files'
    AND auth.uid()::text = (storage.foldername(name))[1]
  );

Owner-Based Access:

create policy "Individual user Access"
on storage.objects for select
to authenticated
using ( (select auth.uid()) = owner_id::uuid );

Advanced Policy Patterns

Restrict by File Extension:

create policy "Only allow PNG uploads"
on storage.objects
for insert
to authenticated
with check (
  bucket_id = 'cats' and storage.extension(name) = 'png'
);

Restrict to Specific Folder:

create policy "Allow authenticated uploads"
on storage.objects
for insert
to authenticated
with check (
  (storage.foldername(name))[1] = 'private'
);

User Folder with Bucket Restriction:

create policy "Allow authenticated uploads"
on storage.objects
for insert
to authenticated
with check (
  bucket_id = 'my_bucket_id' and
  (storage.foldername(name))[1] = (select auth.uid()::text)
);

Restrict by Bucket:

create policy "policy_name"
on storage.objects for insert to authenticated with check (
  bucket_id = 'my_bucket_id'
);

Role-Based Access:

create policy "Manager can view all files in the bucket 'teams'"
on storage.objects
for select
to manager
using (
  bucket_id = 'teams'
);

Complete Setup Example

-- Set up Storage bucket
insert into storage.buckets (id, name, public)
values ('avatars', 'avatars', true);

-- Policy: Anyone can view avatar images
create policy "Avatar images are publicly accessible"
  on storage.objects for select
  using (bucket_id = 'avatars');

-- Policy: Authenticated users can upload avatars
create policy "Anyone can upload an avatar"
  on storage.objects for insert
  with check (
    bucket_id = 'avatars'
    AND auth.role() = 'authenticated'
  );

-- Policy: Users can update their own avatars
create policy "Users can update own avatar"
  on storage.objects for update
  using (
    auth.uid()::text = (storage.foldername(name))[1]
    AND bucket_id = 'avatars'
  );

-- Policy: Users can delete their own avatars
create policy "Users can delete own avatar"
  on storage.objects for delete
  using (
    auth.uid()::text = (storage.foldername(name))[1]
    AND bucket_id = 'avatars'
  );

6. Storage Helper Functions

storage.foldername(name)

Extracts folder path components from object name.

-- Returns array of folder names
(storage.foldername('folder1/folder2/file.png'))[1] -- 'folder1'
(storage.foldername('folder1/folder2/file.png'))[2] -- 'folder2'

storage.extension(name)

Extracts file extension from object name.

storage.extension('file.png') -- 'png'
storage.extension('document.pdf') -- 'pdf'

7. Access Control via Edge Functions

For complex access control scenarios, use Edge Functions to proxy private storage:

const ALLOWED_ORIGINS = ['http://localhost:8000']
const corsHeaders = {
  'Access-Control-Allow-Origin': ALLOWED_ORIGINS.join(','),
  'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type, range, if-match',
  'Access-Control-Expose-Headers': 'range, accept-ranges, etag',
  'Access-Control-Max-Age': '300',
}

Deno.serve((req) => {
  if (req.method === 'OPTIONS') {
    return new Response('ok', { headers: corsHeaders })
  }

  // Check origin
  const origin = req.headers.get('Origin')
  if (!origin || !ALLOWED_ORIGINS.includes(origin)) {
    return new Response('Not Allowed', { status: 405 })
  }

  const reqUrl = new URL(req.url)
  const url = `${Deno.env.get('SUPABASE_URL')}/storage/v1/object/authenticated${reqUrl.pathname}`

  const { method, headers } = req
  const modHeaders = new Headers(headers)
  modHeaders.append('authorization', `Bearer ${Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!}`)

  return fetch(url, { method, headers: modHeaders })
})

8. Best Practices

Security

  1. Always enable RLS on storage.objects when using storage
  2. Use separate buckets for public and private content
  3. Organize files by user ID in folder structure for easy access control
  4. Validate file types and sizes at both client and policy level
  5. Use signed URLs for temporary access to private files
  6. Never expose service role key to client-side code

Performance

  1. Use public buckets for static assets with high CDN cache hit ratio
  2. Set appropriate cache control headers for uploaded files
  3. Use image transformations instead of uploading multiple sizes
  4. Implement resumable uploads for large files (>6MB)
  5. Batch operations when possible (e.g., createSignedUrls for multiple files)

Organization

  1. Name buckets descriptively (e.g., 'user-avatars', 'product-images')
  2. Use folder structure for logical organization (e.g., userId/avatars/filename.png)
  3. Include metadata in upload options for better file management
  4. Set file size limits on buckets to prevent abuse
  5. Use allowed MIME types to restrict upload types

Error Handling

  1. Always check for errors after storage operations
  2. Handle network failures gracefully with retry logic
  3. Provide user feedback during uploads and downloads
  4. Validate files on client before uploading
  5. Log errors for debugging and monitoring

9. Image Transformations

Supabase Storage includes built-in image transformation capabilities:

Available Transformations:

  • width: Resize width
  • height: Resize height
  • quality: Compression quality (1-100)
  • format: Convert format (webp, jpeg, png)

Example:

const { data } = supabase
  .storage
  .from('avatars')
  .getPublicUrl('avatar.jpg', {
    transform: {
      width: 400,
      height: 400,
      quality: 80,
      format: 'webp'
    }
  })

Summary

This comprehensive Supabase Storage skill covers:

  1. Bucket Management - Create, configure, and manage storage buckets
  2. File Operations - Upload, download, list, move, copy, and delete files
  3. URL Generation - Public URLs, signed URLs, and signed upload URLs
  4. RLS Policies - Comprehensive access control patterns
  5. Helper Functions - SQL utilities for path and extension manipulation
  6. Edge Function Integration - Advanced access control scenarios
  7. Best Practices - Security, performance, and organization guidelines
  8. Image Transformations - Built-in image processing

Use this skill whenever working with Supabase Storage to ensure best practices, security, and optimal performance.

适合场景

01

研究助手

02

事实核查

03

知识库问答

04

带来源的搜索总结

能力概览

能力 1

组合搜索和大模型调用

能力 2

支持多来源检索和总结

能力 3

强调引用来源和事实核查

能力 4

适合研究型 Agent 流程

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Claude Code

26.57%
按下载量换算22

Codex

23.32%
按下载量换算19

trae

17.16%
按下载量换算14

Antigravity

13.71%
按下载量换算11

windsurf

7.79%
按下载量换算6

Gemini CLI

3.07%
按下载量换算3

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。

来源信息

继续浏览同类 Skills