SU

supabase-debug-bundle

Automates the collection of Supabase diagnostic bundles, including connection and auth logs, for support escalation.

Install

mkdir -p .claude/skills/supabase-debug-bundle && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/6023" && unzip -o skill.zip -d .claude/skills/supabase-debug-bundle && rm skill.zip

Installs to .claude/skills/supabase-debug-bundle

Activation

This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.

Collect Supabase diagnostic info for troubleshooting and support tickets.
73 charsno explicit “when” trigger
Beginner

Key capabilities

  • Collect Supabase diagnostic information
  • Test Supabase connectivity to REST and Auth endpoints
  • Probe Realtime, Storage, and RLS subsystems
  • Package diagnostics into a single archive
  • Identify SDK and CLI versions

How it works

The skill collects diagnostic data by testing various Supabase services and packaging the results into an archive. It checks SDK versions and environment variables.

Inputs & outputs

You give it
Supabase project environment variables and configuration
You get back
A redacted diagnostic bundle containing connectivity, auth, Realtime, Storage, and RLS status

When to use supabase-debug-bundle

  • Debug Supabase connection failures
  • Prepare diagnostic logs for support tickets
  • Audit Supabase RLS policy configurations
  • Verify Realtime and Storage service status

About this skill

Supabase Debug Bundle

Overview

Collect a comprehensive, redacted diagnostic bundle from a Supabase project. Tests connectivity, auth, Realtime, Storage, RLS policy behavior, and database health — then packages everything into a single archive safe for sharing with Supabase support.

Current State

!node --version 2>/dev/null || echo 'Node.js not found' !npx supabase --version 2>/dev/null || echo 'Supabase CLI not found' !npm list @supabase/supabase-js 2>/dev/null | grep supabase || echo '@supabase/supabase-js not installed'

Prerequisites

  • Node.js 18+ with @supabase/supabase-js v2 installed in the project
  • Supabase CLI installed (npm i -g supabase or npx supabase)
  • Environment variables set: SUPABASE_URL and SUPABASE_ANON_KEY (minimum); SUPABASE_SERVICE_ROLE_KEY for full diagnostics
  • Project linked via supabase link --project-ref <ref> (for CLI commands)

Instructions

Step 1: Gather Environment and Connectivity

Collect SDK version, project URL, key type, and test basic connectivity against the REST and Auth endpoints.

import { createClient } from '@supabase/supabase-js'

const url = process.env.SUPABASE_URL!
const anonKey = process.env.SUPABASE_ANON_KEY!
const serviceKey = process.env.SUPABASE_SERVICE_ROLE_KEY

// Identify which key is in use
const keyType = serviceKey ? 'service_role' : 'anon'
const supabase = createClient(url, serviceKey ?? anonKey, {
  auth: { autoRefreshToken: false, persistSession: false }
})

const diagnostics: Record<string, unknown> = {}

// 1a — SDK + environment
diagnostics.environment = {
  supabase_js_version: require('@supabase/supabase-js/package.json').version,
  node_version: process.version,
  project_url: url.replace(/https:\/\/([^.]+)\..*/, 'https://$1.***'),
  key_type: keyType,
  timestamp: new Date().toISOString(),
}

// 1b — REST API connectivity
const restStart = Date.now()
const restRes = await fetch(`${url}/rest/v1/`, {
  headers: { apikey: anonKey, Authorization: `Bearer ${anonKey}` },
})
diagnostics.rest_api = {
  status: restRes.status,
  latency_ms: Date.now() - restStart,
  ok: restRes.ok,
}

// 1c — Auth health
const authStart = Date.now()
const { data: sessionData, error: sessionErr } = await supabase.auth.getSession()
diagnostics.auth = {
  status: sessionErr ? `error: ${sessionErr.message}` : 'ok',
  has_session: !!sessionData?.session,
  latency_ms: Date.now() - authStart,
}

// 1d — Database connectivity probe
const dbStart = Date.now()
const { error: dbErr } = await supabase.from('_test_ping').select('*').limit(1)
diagnostics.database = {
  // 42P01 = table doesn't exist, which proves the connection works
  status: (!dbErr || dbErr.code === '42P01') ? 'connected' : `error: ${dbErr.code}`,
  latency_ms: Date.now() - dbStart,
}

console.log(JSON.stringify(diagnostics, null, 2))

What to check: REST API should return 200. Auth should return ok. Database probe returning 42P01 (relation not found) is normal — it confirms the PostgREST connection works.

Step 2: Test Realtime, Storage, and RLS

Probe the three subsystems that cause the most support tickets.

// 2a — Realtime subscription test
const realtimeResult = await new Promise<Record<string, unknown>>((resolve) => {
  const timeout = setTimeout(() => {
    resolve({ status: 'timeout', detail: 'No SUBSCRIBED event within 5s' })
  }, 5000)

  const channel = supabase.channel('debug-probe')
  channel.subscribe((status) => {
    if (status === 'SUBSCRIBED') {
      clearTimeout(timeout)
      channel.unsubscribe()
      resolve({ status: 'ok', detail: 'Channel subscribed successfully' })
    } else if (status === 'CHANNEL_ERROR') {
      clearTimeout(timeout)
      channel.unsubscribe()
      resolve({ status: 'error', detail: 'CHANNEL_ERROR on subscribe' })
    }
  })
})
diagnostics.realtime = realtimeResult

// 2b — Storage bucket listing
const { data: buckets, error: storageErr } = await supabase.storage.listBuckets()
diagnostics.storage = {
  status: storageErr ? `error: ${storageErr.message}` : 'ok',
  bucket_count: buckets?.length ?? 0,
  buckets: buckets?.map((b) => ({ name: b.name, public: b.public })) ?? [],
}

// 2c — RLS comparison: anon vs service_role
// Query the same table with both key types to detect RLS misconfiguration
if (serviceKey) {
  const anonClient = createClient(url, anonKey, {
    auth: { autoRefreshToken: false, persistSession: false },
  })
  // Pick the first public table from pg_tables (or fall back)
  const { data: tables } = await supabase
    .from('information_schema.tables' as any)
    .select('table_name')
    .eq('table_schema', 'public')
    .limit(1)

  const testTable = tables?.[0]?.table_name
  if (testTable) {
    const { count: anonCount } = await anonClient
      .from(testTable)
      .select('*', { count: 'exact', head: true })
    const { count: serviceCount } = await supabase
      .from(testTable)
      .select('*', { count: 'exact', head: true })
    diagnostics.rls = {
      table: testTable,
      anon_visible_rows: anonCount ?? 0,
      service_role_visible_rows: serviceCount ?? 0,
      rls_active: (anonCount ?? 0) !== (serviceCount ?? 0),
    }
  } else {
    diagnostics.rls = { status: 'skipped', detail: 'No public tables found' }
  }
} else {
  diagnostics.rls = { status: 'skipped', detail: 'No service_role key — cannot compare' }
}

What to check: Realtime should reach SUBSCRIBED within 5 seconds. Storage should list buckets without error. RLS comparison showing identical row counts for anon and service_role on a table you expect to be protected means RLS policies may be missing.

Step 3: Collect Database Health and Package the Bundle

Pull database statistics via the Supabase CLI inspect commands and the platform status page, then archive everything.

#!/bin/bash
set -euo pipefail

BUNDLE_DIR="supabase-debug-$(date +%Y%m%d-%H%M%S)"
mkdir -p "$BUNDLE_DIR"

# 3a — Supabase CLI status (local dev)
npx supabase status > "$BUNDLE_DIR/cli-status.txt" 2>&1 || echo "CLI status unavailable (not linked or no local dev)" > "$BUNDLE_DIR/cli-status.txt"

# 3b — Database inspection via CLI
npx supabase inspect db table-sizes   > "$BUNDLE_DIR/table-sizes.txt"   2>&1 || true
npx supabase inspect db index-usage   > "$BUNDLE_DIR/index-usage.txt"   2>&1 || true
npx supabase inspect db cache-hit     > "$BUNDLE_DIR/cache-hit.txt"     2>&1 || true
npx supabase inspect db seq-scans     > "$BUNDLE_DIR/seq-scans.txt"     2>&1 || true
npx supabase inspect db long-running-queries > "$BUNDLE_DIR/long-queries.txt" 2>&1 || true
npx supabase inspect db bloat         > "$BUNDLE_DIR/bloat.txt"         2>&1 || true
npx supabase inspect db replication-slots > "$BUNDLE_DIR/replication.txt" 2>&1 || true

# 3c — Platform status page
curl -sf https://status.supabase.com/api/v2/status.json \
  | python3 -m json.tool > "$BUNDLE_DIR/platform-status.json" 2>/dev/null \
  || echo '{"error": "Could not reach status.supabase.com"}' > "$BUNDLE_DIR/platform-status.json"

# 3d — Redact secrets from all collected files
find "$BUNDLE_DIR" -type f -exec sed -i \
  -e 's/eyJ[A-Za-z0-9_-]\{20,\}\(\.[A-Za-z0-9_-]*\)*/[JWT_REDACTED]/g' \
  -e 's/sbp_[A-Za-z0-9]\{20,\}/[SBP_KEY_REDACTED]/g' \
  -e 's/[A-Za-z0-9._%+-]\+@[A-Za-z0-9.-]\+\.[A-Za-z]\{2,\}/[EMAIL_REDACTED]/g' {} +

# 3e — Package
tar czf "${BUNDLE_DIR}.tar.gz" "$BUNDLE_DIR"
echo "Debug bundle created: ${BUNDLE_DIR}.tar.gz"
echo "Contents:"
ls -lh "$BUNDLE_DIR"/

What to check: Review cache-hit.txt — index and table hit rates below 99% indicate memory pressure. bloat.txt values above 50% on large tables warrant a VACUUM. seq-scans.txt highlights tables needing indexes.

Output

The skill produces supabase-debug-YYYYMMDD-HHMMSS.tar.gz containing:

FileContents
cli-status.txtLocal Supabase stack status (services, ports, URLs)
table-sizes.txtAll tables with row counts and disk usage
index-usage.txtIndex scan frequency — unused indexes are candidates for removal
cache-hit.txtBuffer cache and index cache hit ratios
seq-scans.txtTables with high sequential scan counts (missing indexes)
long-queries.txtCurrently running queries over the duration threshold
bloat.txtTable and index bloat percentages
replication.txtReplication slot status (relevant for Realtime)
platform-status.jsonSupabase platform health from status.supabase.com

Plus the TypeScript diagnostics output (connectivity, auth, Realtime, Storage, RLS) printed to stdout.

All JWT tokens, Supabase project keys (sbp_*), and email addresses are automatically redacted before archiving.

Error Handling

SymptomCauseFix
REST API returns 401Invalid or expired anon keyRegenerate key in Dashboard > Settings > API
REST API returns 000 or times outWrong SUPABASE_URL or project pausedVerify URL; unpause project in Dashboard
Realtime returns CHANNEL_ERRORWebSocket blocked by firewall/proxyCheck corporate proxy; try from a different network
Realtime times out (5s)Realtime addon not enabled or quota hitEnable Realtime on the table in Dashboard > Database > Replication
Storage listBuckets returns 403RLS enabled on storage without policyAdd a storage policy or use service_role key
supabase inspect db failsCLI not linked to remote projectRun supabase link --project-ref <ref> first
cache-hit below 95%Database instance too small for workloadUpgrade compute size or optimize queries
RLS shows identical countsNo RLS policies on the tableAdd policies via ALTER TABLE ... ENABLE ROW LEVEL SECURITY
pg_stat_statements not availableExtension not enabledEnable in Dashboard > Database > Extensions

Examples

Quick connectivity check (no service key needed):

import { createClient } from '@supabase/

---

*Content truncated.*

Prerequisites

Node.js 18+ with @supabase/supabase-js v2 installedSupabase CLI installedSUPABASE_URL and SUPABASE_ANON_KEY environment variablesProject linked via supabase link --project-ref <ref>

How it compares

This skill automates the collection of complete Supabase diagnostic data, which is more thorough than manual checks for troubleshooting and support.

Compared to similar skills

supabase-debug-bundle side by side with the closest alternatives in the catalog.

SkillInstallsUpdatedSafetyDifficulty
supabase-debug-bundle (this skill)127dCautionBeginner
redis-inspect66moReviewBeginner
optimizing-performance12moReviewIntermediate
semaphore-third-party-licenses02moReviewIntermediate

Try saying

Example prompts that trigger this skill in your AI assistant.

More by jeremylongshore

View all by jeremylongshore

analyzing-logs

jeremylongshore

Analyze application logs to detect performance issues, identify error patterns, and improve stability by extracting key insights.

14123

ollama-setup

jeremylongshore

Configure auto-configure Ollama when user needs local LLM deployment, free AI alternatives, or wants to eliminate hosted API costs. Trigger phrases: "install ollama", "local AI", "free LLM", "self-hosted AI", "replace OpenAI", "no API costs". Use when appropriate context detected. Trigger with relevant phrases based on skill purpose.

1167

backtesting-trading-strategies

jeremylongshore

Backtest crypto and traditional trading strategies against historical data. Calculates performance metrics (Sharpe, Sortino, max drawdown), generates equity curves, and optimizes strategy parameters. Use when user wants to test a trading strategy, validate signals, or compare approaches. Trigger with phrases like "backtest strategy", "test trading strategy", "historical performance", "simulate trades", "optimize parameters", or "validate signals".

1071

generating-database-seed-data

jeremylongshore

Process this skill enables AI assistant to generate realistic test data and database seed scripts for development and testing environments. it uses faker libraries to create realistic data, maintains relational integrity, and allows configurable data volumes. u... Use when working with databases or data models. Trigger with phrases like 'database', 'query', or 'schema'.

1033

cursor-codebase-indexing

jeremylongshore

Execute set up and optimize Cursor codebase indexing. Triggers on "cursor index setup", "codebase indexing", "index codebase", "cursor semantic search". Use when working with cursor codebase indexing functionality. Trigger with phrases like "cursor codebase indexing", "cursor indexing", "cursor".

885

testing-mobile-apps

jeremylongshore

Execute mobile app testing on iOS and Android devices/simulators. Use when performing specialized testing. Trigger with phrases like "test mobile app", "run iOS tests", or "validate Android functionality".

810

Search skills

Search the agent skills registry