Token导航 LogoToken导航

Agent Skill · 研究检索

supabase-auth-memory(Supabase auth 记忆)

用于辅助安全审计、权限检查、凭据风险、认证流程和常见漏洞排查。它适合让 Agent 梳理敏感配置、检查依赖风险、分析鉴权逻辑或生成安全复核清单。使用时不能把工具输出直接当最终结论,涉及密钥、令牌、用户数据或生产系统时,应先确认最小权限、脱敏方式和操作边界。

supabase-auth-memory 是研究检索类 Agent Skill,可用宿主为 Codex、Claude、Cursor、Gemini CLI,通过GitHub 仓库获取,权限为接触敏感数据;许可证为 MIT,第三方扫描有提醒项,按安装量在研究检索类的 73,675 个 Skill 里排第 60,207。

总安装 372周安装 16GitHub Stars 公开资料未说明下载 131核验 2026-05-01

安装说明

本站只整理中文说明,不托管安装包,也不代用户安装。
GitHub
许可证
MIT

安装方式

通过对话安装

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

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

命令行安装

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

skills.shnpx skills
npx skills add https://github.com/fernandofuc/nextjs-claude-setup --skill supabase-auth-memory

这个 Skill 是做什么的

研究检索类 Skill 主要解决「找资料、核对事实、把来源整理清楚」的问题,通常会让助手先检索再总结。

辅助安全审计和认证流程分析,支持常见漏洞排查。适合梳理敏感配置和检查依赖风险。适用宿主包括 Codex、Claude、Cursor、Gemini CLI,接入前应确认版本、权限和运行环境要求。通过 npx 命令从指定 GitHub 仓库安装并使用该技能。涉及密钥或用户数据时需确认最小权限和操作边界。

supabase-auth-memory 属于研究检索类 Skill,可作为该场景下的辅助能力补充。

来源仓库内路径:skills/supabase-auth-memory

上手步骤

4 步
  1. 1

    确认自己的宿主工具

    公开资料标注支持 Codex、Claude、Cursor、Gemini CLI;先确认自己用的是其中之一,再按对应工具的 Skills 目录放置。

  2. 2

    拿到安装命令

    可以直接复制的命令是 npx skills add https://github.com/fernandofuc/nextjs-claude-setup --skill supaba…;命令里的占位符换成自己的路径或密钥再执行。

  3. 3

    安装后重启宿主

    命令执行完要完全退出宿主工具再打开,让新装的 Skill 被重新扫描到,否则列表里可能看不到。

  4. 4

    按最小权限试用

    它需要接触敏感数据,先在测试目录或测试账号里跑,确认没问题再放到正式项目。

常见问题

6 条

supabase-auth-memory 怎么安装?

在终端执行 npx skills add https://github.com/fernandofuc/nextjs-claude-setup --skill supabase-auth-me…。装完完全退出宿主工具再打开,让它重新扫描本地 Skill。

supabase-auth-memory 支持哪些 AI 工具?

公开资料标注支持 Codex、Claude、Cursor、Gemini CLI。其他工具只要能读取本地 Skill 目录,一般也能手动放进去,但要自己确认触发方式是否一致。

supabase-auth-memory 需要什么权限?

权限级别是接触敏感数据。该 Skill 可能接触密钥、Token、环境变量或敏感配置,应进入高风险复核队列,默认不自动发布。

supabase-auth-memory 是免费的吗?

来源标注的许可证是 MIT。本站不代收任何费用,也不托管安装包;能否商用、要不要署名,以许可证原文为准。

supabase-auth-memory 用的人多吗?

公开数据是累计安装 372 次,近一周安装 16 次,下载 131 次。这些数字来自第三方目录统计,只能当作热度参考,不代表质量或安全性。

supabase-auth-memory 安全吗?

第三方扫描有提醒项,说明存在需要人工确认的行为。安装前请打开源码看清它读了什么、联网到哪里。

值得选的地方和要先想清楚的地方

值得选的地方

  • 同时适配 4 种工具,换客户端不用重新找替代品。
  • 3 个目录同时收录,说明这个 Skill 流传比较广。
  • 许可证明确为 MIT,商用和分发边界好判断。

先想清楚的地方

  • 需要接触敏感数据,装到常用环境前要先评估影响面。
  • 第三方扫描存在提醒项或未通过项,需要人工逐条确认。
  • 第三方目录整理,版本更新和行为细节以来源仓库为准。

适不适合你

更适合

  • 已经在用 Codex,想直接扩展它能力的人。
  • 需要处理研究检索类任务、又不想每次都手写提示词的人。

不太适合

  • 环境里有大量密钥、凭证,不方便给第三方 Skill 读取的人。
  • 需要厂商级技术支持和 SLA 的生产系统。

研究检索类 Skill 对比

6 个同类
Skill总安装GitHub 星权限许可证扫描
find-skills

寻找技能 · Codex、Claude

31,199,81316,486操作浏览器MIT有提醒
self-improving-agent

自我改进 Agent · OpenClaw

16,464,0023,396接触敏感数据MIT-0通过
soultrace

灵魂追踪 · Codex、Claude

7,588,94412需要联网未明确有提醒
self-improving

自我完善 · OpenClaw

6,829,2841,046需要联网MIT-0通过
microsoft-foundry

微软代工厂 · Codex、Claude

6,614,144764调用外部服务未明确有提醒
supabase-auth-memory

Supabase auth 记忆 · 本页

372—接触敏感数据MIT有提醒

按安装量取同分类前几名;数字来自第三方目录统计,只作热度参考,不代表质量结论。

SKILL.md 原文

Supabase Auth + Memory System

Purpose

Implement user authentication and persistent AI conversation memory using Supabase as unified backend.

When to Use

  • Need user authentication in SaaS app
  • Want conversation history across devices
  • Building multi-tenant AI applications
  • Need SQL-based memory for agents
  • Syncing state between localStorage and cloud

Quick Start

Installation

npm install @supabase/supabase-js
npm install zustand zustand/middleware

Environment Variables

NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
SUPABASE_SERVICE_KEY=your-service-key  # Backend only

Database Schema

Core Tables

-- Conversations table
CREATE TABLE conversations (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  user_id UUID REFERENCES auth.users(id) ON DELETE CASCADE,
  title TEXT NOT NULL,
  created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
  updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
  metadata JSONB DEFAULT '{}'::jsonb,

  -- Indexes
  CONSTRAINT conversations_user_id_fkey FOREIGN KEY (user_id)
    REFERENCES auth.users(id) ON DELETE CASCADE
);

CREATE INDEX idx_conversations_user ON conversations(user_id);
CREATE INDEX idx_conversations_updated ON conversations(updated_at DESC);

-- Messages table
CREATE TABLE messages (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  conversation_id UUID REFERENCES conversations(id) ON DELETE CASCADE,
  role TEXT NOT NULL CHECK (role IN ('user', 'assistant', 'system')),
  content TEXT NOT NULL,
  tool_used TEXT,
  tool_result JSONB,
  reasoning_details JSONB,
  created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),

  -- Indexes
  CONSTRAINT messages_conversation_id_fkey FOREIGN KEY (conversation_id)
    REFERENCES conversations(id) ON DELETE CASCADE
);

CREATE INDEX idx_messages_conversation ON messages(conversation_id);
CREATE INDEX idx_messages_created ON messages(created_at DESC);

-- User preferences (config storage)
CREATE TABLE user_preferences (
  user_id UUID PRIMARY KEY REFERENCES auth.users(id) ON DELETE CASCADE,
  preferences JSONB NOT NULL DEFAULT '{}'::jsonb,
  created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
  updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

-- Auto-update timestamp trigger
CREATE OR REPLACE FUNCTION update_updated_at()
RETURNS TRIGGER AS $$
BEGIN
  NEW.updated_at = NOW();
  RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER conversations_updated_at
BEFORE UPDATE ON conversations
FOR EACH ROW EXECUTE FUNCTION update_updated_at();

Row Level Security (RLS) Policies

-- Enable RLS
ALTER TABLE conversations ENABLE ROW LEVEL SECURITY;
ALTER TABLE messages ENABLE ROW LEVEL SECURITY;
ALTER TABLE user_preferences ENABLE ROW LEVEL SECURITY;

-- Conversations policies
CREATE POLICY "Users can view own conversations"
ON conversations FOR SELECT
USING (auth.uid() = user_id);

CREATE POLICY "Users can create own conversations"
ON conversations FOR INSERT
WITH CHECK (auth.uid() = user_id);

CREATE POLICY "Users can update own conversations"
ON conversations FOR UPDATE
USING (auth.uid() = user_id);

CREATE POLICY "Users can delete own conversations"
ON conversations FOR DELETE
USING (auth.uid() = user_id);

-- Messages policies
CREATE POLICY "Users can view own messages"
ON messages FOR SELECT
USING (
  conversation_id IN (
    SELECT id FROM conversations WHERE user_id = auth.uid()
  )
);

CREATE POLICY "Users can create messages"
ON messages FOR INSERT
WITH CHECK (
  conversation_id IN (
    SELECT id FROM conversations WHERE user_id = auth.uid()
  )
);

-- User preferences policies
CREATE POLICY "Users can view own preferences"
ON user_preferences FOR SELECT
USING (auth.uid() = user_id);

CREATE POLICY "Users can upsert own preferences"
ON user_preferences FOR INSERT
WITH CHECK (auth.uid() = user_id);

CREATE POLICY "Users can update own preferences"
ON user_preferences FOR UPDATE
USING (auth.uid() = user_id);

Frontend Integration

Supabase Client Setup

// lib/supabase.ts
import { createClient } from '@supabase/supabase-js'

export const supabase = createClient(
  process.env.NEXT_PUBLIC_SUPABASE_URL!,
  process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
)

// Get current user
export async function getCurrentUser() {
  const { data: { user } } = await supabase.auth.getUser()
  return user
}

Zustand Store with Supabase Sync

// stores/conversationStore.ts
import { create } from 'zustand'
import { persist, createJSONStorage } from 'zustand/middleware'
import { supabase } from '@/lib/supabase'

interface Message {
  id: string
  role: 'user' | 'assistant' | 'system'
  content: string
  tool_used?: string
  created_at: string
}

interface ConversationStore {
  // State
  messages: Message[]
  conversationId: string | null
  isSyncing: boolean

  // Local actions (optimistic UI)
  addMessage: (message: Omit<Message, 'id' | 'created_at'>) => void
  clearMessages: () => void

  // Supabase sync actions
  createConversation: (title: string) => Promise<string>
  loadConversation: (conversationId: string) => Promise<void>
  saveToSupabase: () => Promise<void>
  syncWithSupabase: () => Promise<void>
}

export const useConversationStore = create<ConversationStore>()(
  persist(
    (set, get) => ({
      // Initial state
      messages: [],
      conversationId: null,
      isSyncing: false,

      // Add message optimistically
      addMessage: (message) => {
        const newMessage: Message = {
          ...message,
          id: crypto.randomUUID(),
          created_at: new Date().toISOString()
        }

        set(state => ({
          messages: [...state.messages, newMessage]
        }))

        // Auto-save to Supabase (non-blocking)
        get().saveToSupabase()
      },

      // Clear messages
      clearMessages: () => set({ messages: [], conversationId: null }),

      // Create new conversation in Supabase
      createConversation: async (title) => {
        const user = await getCurrentUser()
        if (!user) throw new Error('Not authenticated')

        const { data, error } = await supabase
          .from('conversations')
          .insert({ user_id: user.id, title })
          .select()
          .single()

        if (error) throw error

        set({ conversationId: data.id })
        return data.id
      },

      // Load conversation from Supabase
      loadConversation: async (conversationId) => {
        set({ isSyncing: true })

        const { data, error } = await supabase
          .from('messages')
          .select('*')
          .eq('conversation_id', conversationId)
          .order('created_at', { ascending: true })

        if (error) throw error

        set({
          messages: data || [],
          conversationId,
          isSyncing: false
        })
      },

      // Save messages to Supabase
      saveToSupabase: async () => {
        const { messages, conversationId } = get()
        if (!conversationId) return

        set({ isSyncing: true })

        // Find new messages (not yet in Supabase)
        const newMessages = messages.filter(m => !m.id.startsWith('uuid'))

        if (newMessages.length > 0) {
          const { error } = await supabase
            .from('messages')
            .insert(
              newMessages.map(m => ({
                conversation_id: conversationId,
                role: m.role,
                content: m.content,
                tool_used: m.tool_used
              }))
            )

          if (error) console.error('Failed to save to Supabase:', error)
        }

        set({ isSyncing: false })
      },

      // Sync with Supabase (merge local + remote)
      syncWithSupabase: async () => {
        const { conversationId } = get()
        if (!conversationId) return

        await get().loadConversation(conversationId)
      }
    }),
    {
      name: 'conversation-storage',
      storage: createJSONStorage(() => localStorage),

      // Only persist specific fields
      partialize: (state) => ({
        messages: state.messages,
        conversationId: state.conversationId
      })
    }
  )
)

User Preferences Store

// stores/preferencesStore.ts
import { create } from 'zustand'
import { persist } from 'zustand/middleware'
import { supabase, getCurrentUser } from '@/lib/supabase'

interface Preferences {
  theme: 'light' | 'dark'
  temperature: number
  model: string
  [key: string]: any
}

interface PreferencesStore {
  preferences: Preferences
  updatePreferences: (updates: Partial<Preferences>) => void
  syncWithSupabase: () => Promise<void>
}

export const usePreferencesStore = create<PreferencesStore>()(
  persist(
    (set, get) => ({
      preferences: {
        theme: 'dark',
        temperature: 0.7,
        model: 'openai/gpt-4o'
      },

      updatePreferences: (updates) => {
        set(state => ({
          preferences: { ...state.preferences, ...updates }
        }))

        // Auto-sync to Supabase
        get().syncWithSupabase()
      },

      syncWithSupabase: async () => {
        const user = await getCurrentUser()
        if (!user) return

        const { preferences } = get()

        await supabase
          .from('user_preferences')
          .upsert({
            user_id: user.id,
            preferences
          })
      }
    }),
    {
      name: 'user-preferences',
      onRehydrateStorage: () => (state) => {
        // Load from Supabase after localStorage rehydration
        state?.syncWithSupabase()
      }
    }
  )
)

Real-time Subscriptions

// hooks/useRealtimeMessages.ts
import { useEffect } from 'react'
import { supabase } from '@/lib/supabase'
import { useConversationStore } from '@/stores/conversationStore'

export function useRealtimeMessages(conversationId: string) {
  const addMessage = useConversationStore(state => state.addMessage)

  useEffect(() => {
    const channel = supabase
      .channel(`conversation:${conversationId}`)
      .on(
        'postgres_changes',
        {
          event: 'INSERT',
          schema: 'public',
          table: 'messages',
          filter: `conversation_id=eq.${conversationId}`
        },
        (payload) => {
          addMessage(payload.new as any)
        }
      )
      .subscribe()

    return () => {
      supabase.removeChannel(channel)
    }
  }, [conversationId, addMessage])
}

Authentication Patterns

Sign Up

async function signUp(email: string, password: string) {
  const { data, error } = await supabase.auth.signUp({
    email,
    password,
    options: {
      emailRedirectTo: `${window.location.origin}/auth/callback`
    }
  })

  if (error) throw error
  return data
}

Sign In

async function signIn(email: string, password: string) {
  const { data, error } = await supabase.auth.signInWithPassword({
    email,
    password
  })

  if (error) throw error
  return data
}

OAuth (Google, GitHub, etc.)

async function signInWithOAuth(provider: 'google' | 'github') {
  const { data, error } = await supabase.auth.signInWithOAuth({
    provider,
    options: {
      redirectTo: `${window.location.origin}/auth/callback`
    }
  })

  if (error) throw error
  return data
}

Supabase MCP Integration

Setup (.mcp.json)

{
  "mcpServers": {
    "supabase": {
      "url": "https://mcp.supabase.com/mcp?project_ref=YOUR_PROJECT_REF",
      "transport": "streamable-http",
      "auth": {
        "type": "oauth"
      }
    }
  }
}

Available MCP Tools

  • Create/manage projects
  • Design tables & migrations
  • Query data with SQL
  • Generate TypeScript types
  • Manage configurations

Best Practices

  1. Security First

- Always enable RLS on all tables - Use service key only on server - Validate user ownership in policies

  1. Hybrid Storage

- localStorage for offline/instant UX - Supabase for cross-device sync - Background sync with debouncing

  1. Optimistic UI

- Update UI immediately - Sync to Supabase in background - Handle conflicts gracefully

  1. Real-time Updates

- Use subscriptions for collaboration - Clean up subscriptions on unmount - Debounce rapid updates

  1. Error Handling

- Retry failed syncs - Show sync status to user - Fallback to localStorage

  1. Performance

- Index frequently queried columns - Use JSONB for flexible metadata - Implement pagination for large datasets

Common Patterns

Multi-tenant SaaS

-- Add tenant isolation
CREATE TABLE organizations (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  name TEXT NOT NULL,
  created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

CREATE TABLE organization_members (
  organization_id UUID REFERENCES organizations(id),
  user_id UUID REFERENCES auth.users(id),
  role TEXT NOT NULL CHECK (role IN ('owner', 'admin', 'member')),
  PRIMARY KEY (organization_id, user_id)
);

-- Update RLS policies for organization isolation
CREATE POLICY "Organization members can view conversations"
ON conversations FOR SELECT
USING (
  user_id IN (
    SELECT user_id FROM organization_members
    WHERE organization_id = (
      SELECT organization_id FROM organization_members
      WHERE user_id = auth.uid()
    )
  )
);

Resources

平台分布

Claude Code

26.75%
按下载量换算35

Antigravity

22.81%
按下载量换算30

Gemini CLI

18.18%
按下载量换算24

windsurf

13.56%
按下载量换算18

OpenCode

8.41%
按下载量换算11

Cursor

3.64%
按下载量换算5

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

可疑

权限和风险

接触敏感数据

该 Skill 可能接触密钥、Token、环境变量或敏感配置,应进入高风险复核队列,默认不自动发布。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。来源安全扫描存在提醒或未通过项,安装前请自行复核。

继续浏览同类 Skills