一键导入
supabase
Supabase CLI, Postgres performance, and schema patterns. Use for database operations, queries, RLS, and migrations.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Supabase CLI, Postgres performance, and schema patterns. Use for database operations, queries, RLS, and migrations.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Show token / tool usage stats from the local telemetry log. Use when you want to know "which tools am I burning context on", "which skills are expensive", or "was yesterday's session mostly Read/Grep or actually productive".
Parallel quality audit with 7 specialized agents (Opus). Finds bugs, violations, and quality issues. Use audit for fixes, brainstorm for features.
Manage environment variables with Doppler — auto-install CLI, login, link projects, wrap commands with `doppler run`. Replaces scattered .env files with a hub/spoke architecture.
Scaffolds new projects or onboards existing ones. Detects stack, creates monorepo/single-app, configures strict tooling. Use for greenfield or first-time setup.
Archives completed stories from prd.json to reduce token usage.
Autonomous task execution with testing and security. Works through all tasks without stopping.
| name | supabase |
| description | Supabase CLI, Postgres performance, and schema patterns. Use for database operations, queries, RLS, and migrations. |
| triggers | ["db","supabase","postgres","rls","migration","schema","table","database","edge function"] |
| allowed-tools | Bash, Read, Write, Edit, Grep, Glob |
| model | opus |
| user-invocable | true |
Use CLI instead of MCP - more reliable, fewer permission issues.
# Apply migrations (limit output)
supabase db push --project-ref PROJECT_ID 2>&1 | tail -10
# Run SQL directly
supabase db execute --sql "SELECT * FROM table LIMIT 5" --project-ref PROJECT_ID
# Deploy edge functions
supabase functions deploy FUNCTION_NAME --project-ref PROJECT_ID
# Deploy all functions
supabase functions deploy --project-ref PROJECT_ID
# List projects
supabase projects list
# Check status
supabase status --project-ref PROJECT_ID
# Limit output to reduce context
supabase db push 2>&1 | tail -5
# Check if migration exists before applying
supabase db execute --sql "SELECT 1 FROM table LIMIT 1" 2>&1 | grep -q "1" && echo "exists"
# Run in background for long operations
Bash({ command: "supabase functions deploy --project-ref X", run_in_background: true })
Get from CLAUDE.md or:
supabase projects list 2>&1 | grep -E "^\w"
CLI only supports one token at a time. System env var may not match the current project — always check. A 401 means wrong token, do not retry.
# Option 1: Inline token (best for multi-org)
SUPABASE_ACCESS_TOKEN=$SUPABASE_TOKEN_REELR supabase db push --project-ref XXX
# Option 2: Source project's .env.local first
# .env.local is auto-loaded by session-start hook - no need to source
supabase db push --project-ref $SUPABASE_PROJECT_ID
# Option 3: Use --db-url with connection string (bypasses auth)
supabase db execute --db-url "postgresql://postgres:PASSWORD@db.XXX.supabase.co:5432/postgres" --sql "..."
Project .env.local should have:
SUPABASE_ACCESS_TOKEN=sbp_xxx
SUPABASE_PROJECT_ID=xxx
SUPABASE_DB_PASSWORD=xxx
Use Pooler URL (IPv4 compatible), not direct connection:
# Pooler - IPv4 compatible (use this)
psql "postgresql://postgres.REF:PASS@aws-0-REGION.pooler.supabase.com:6543/postgres" -c "SELECT 1"
Get pooler URL: Dashboard > Connect > Connection String > Session Pooler
-- BAD: Full table scan
SELECT * FROM orders WHERE customer_id = 123;
-- GOOD: Add index
CREATE INDEX idx_orders_customer_id ON orders(customer_id);
-- BAD: N+1 queries
SELECT * FROM orders WHERE id = 1;
SELECT * FROM customers WHERE id = (order.customer_id); -- repeated
-- GOOD: Single join
SELECT o.*, c.*
FROM orders o
JOIN customers c ON o.customer_id = c.id
WHERE o.id = 1;
-- BAD: Function call in RLS (slow)
CREATE POLICY "users" ON profiles
USING (user_id = get_current_user_id());
-- GOOD: Use auth.uid() directly
CREATE POLICY "users" ON profiles
USING (user_id = auth.uid());
Supabase default: Transaction mode (pgbouncer)
- Use for serverless/edge functions
- Prepared statements require session mode
- Set pool size based on: max_connections / num_instances
-- Always index foreign keys!
ALTER TABLE orders ADD CONSTRAINT fk_customer
FOREIGN KEY (customer_id) REFERENCES customers(id);
CREATE INDEX idx_orders_customer_id ON orders(customer_id);
| Priority | Category | Impact |
|---|---|---|
| 1 | Query Performance | High - Missing indexes, composite indexes |
| 2 | Connection Management | High - Pooling, limits, idle timeout |
| 3 | Security & RLS | High - RLS basics, RLS performance |
| 4 | Schema Design | High - Data types, PKs, FK indexes, partitioning |
| 5 | Concurrency & Locking | Medium-High - Short transactions, deadlock prevention |
| 6 | Data Access Patterns | Medium - N+1, pagination, batch inserts, upsert |
| File | When to Load |
|---|---|
${CLAUDE_SKILL_DIR}/references/query-missing-indexes.md | Query optimization |
${CLAUDE_SKILL_DIR}/references/conn-pooling.md | Connection issues |
${CLAUDE_SKILL_DIR}/references/security-rls-performance.md | Slow RLS policies |
${CLAUDE_SKILL_DIR}/references/security-rls-basics.md | Setting up RLS |
${CLAUDE_SKILL_DIR}/references/data-n-plus-one.md | Multiple query issues |
${CLAUDE_SKILL_DIR}/references/monitor-explain-analyze.md | Query debugging |
CREATE TABLE IF NOT EXISTS public.[table_name] (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID REFERENCES auth.users(id) ON DELETE CASCADE,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
-- Always enable RLS
ALTER TABLE public.[table_name] ENABLE ROW LEVEL SECURITY;
-- User owns row
CREATE POLICY "Users access own data"
ON public.[table_name] FOR ALL
USING (auth.uid() = user_id);
CREATE TABLE public.profiles (
id UUID PRIMARY KEY REFERENCES auth.users(id) ON DELETE CASCADE,
email TEXT,
full_name TEXT,
avatar_url TEXT,
role TEXT DEFAULT 'user',
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- Auto-create on signup
CREATE OR REPLACE FUNCTION public.handle_new_user()
RETURNS TRIGGER
SECURITY DEFINER
SET search_path = public
AS $$
BEGIN
INSERT INTO public.profiles (id, email)
VALUES (NEW.id, NEW.email);
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER on_auth_user_created
AFTER INSERT ON auth.users
FOR EACH ROW EXECUTE FUNCTION public.handle_new_user();
# View schema
npx supabase db dump --schema public | head -200
# Create migration
npx supabase migration new create_[table_name]
# Apply migration
npx supabase db push
After applying migrations, verify RLS actually works via REST API:
# Test as anonymous (should fail on protected tables)
curl -s 'https://REF.supabase.co/rest/v1/TABLE?select=*&limit=1' \
-H 'apikey: ANON_KEY' \
-H 'Authorization: Bearer ANON_KEY' | head -5
# Should return empty array or 401, NOT actual data
# If data returns, RLS policy is too permissive
For every migration that changes schema, prepare a rollback:
-- Migration: add_column.sql
ALTER TABLE public.items ADD COLUMN status TEXT DEFAULT 'active';
-- Rollback (keep as comment or separate file):
-- ALTER TABLE public.items DROP COLUMN status;
For destructive changes, add columns as nullable with defaults first, migrate data, then drop old columns in a separate migration.
Do:
Avoid:
INSERT policies with WITH CHECK (true) on sensitive tablesUSING (true) on tables containing PII| Rule | When to Load |
|---|---|
${CLAUDE_SKILL_DIR}/rules/rls-patterns.md | RLS policy examples |
${CLAUDE_SKILL_DIR}/rules/security-patterns.md | Security hardening |
${CLAUDE_SKILL_DIR}/rules/multi-account.md | Multi-account CLI setup |
Source: supabase/agent-skills