Cursorist Docs
Supabase

Database Schema

Every table, column, index, and RLS policy in the Cursorist database — explained.

The Cursorist database runs on Supabase (PostgreSQL). It stores users, organizations, teams, and the entire plugin lifecycle — from creation through versioning to installation tracking. Every table has Row Level Security (RLS) enabled, so data access is enforced at the database level.

The entire schema lives in a single migration file: supabase/migrations/001_init.sql. Run it in the SQL Editor to set up everything. This page is a reference for understanding what each table does and how they connect.

Schema Diagram

Loading diagram...

Core Tables

users

Stores every authenticated user. Created automatically when a user signs in via GitHub OAuth for the first time.

ColumnTypeDescription
idUUID (PK)Matches Supabase Auth user ID
github_idTEXTGitHub numeric ID (unique)
github_usernameTEXTGitHub handle (unique)
emailTEXTEmail from GitHub profile
avatar_urlTEXTProfile picture URL
is_adminBOOLEANPlatform admin flag (only one admin allowed)
onboarding_completedBOOLEANWhether user finished the onboarding flow
created_atTIMESTAMPTZAccount creation time
updated_atTIMESTAMPTZLast profile update (auto-managed by trigger)

organizations

Top-level grouping for teams and plugins. Every user who creates an org becomes its owner.

ColumnTypeDescription
idUUID (PK)Organization ID
owner_idUUID (FK → users)The user who created the org
nameTEXTDisplay name
slugTEXTURL-safe identifier (unique)
descriptionTEXTOptional description
avatar_urlTEXTOrg logo/avatar

A trigger (add_owner_to_org_members) automatically adds the owner as a member with role owner when an org is created.

teams

Groups within an organization. Plugins belong to teams, not directly to orgs.

ColumnTypeDescription
idUUID (PK)Team ID
organization_idUUID (FK → organizations)Parent org
nameTEXTDisplay name
slugTEXTURL-safe identifier (unique per org)
descriptionTEXTOptional description

A trigger (add_creator_to_team_members) automatically adds the org owner as a team admin when a team is created.

organization_members

Links users to organizations with a role.

ColumnTypeDescription
user_idUUID (FK → users)Member
organization_idUUID (FK → organizations)Org they belong to
roleENUM (owner, member)Permission level

team_members

Links users to teams with a role. Controls who can create and manage plugins.

ColumnTypeDescription
user_idUUID (FK → users)Member
team_idUUID (FK → teams)Team they belong to
roleENUM (admin, member)Permission level — admins can delete any plugin in the team

Plugin Tables

plugins

The central plugin record. Belongs to a team, authored by a user.

ColumnTypeDescription
idUUID (PK)Plugin ID
team_idUUID (FK → teams)Owning team
author_idUUID (FK → users)Creator
nameTEXTDisplay name
slugTEXTURL-safe identifier (unique per team)
descriptionTEXTShort description
typeENUMCategory: conventions, snippets, templates, workflows, linting, testing, documentation, other
stackTEXT[]Technology tags (e.g. ["typescript", "react"]), indexed with GIN
homepage_urlTEXTExternal homepage link
repository_urlTEXTSource code link
documentation_urlTEXTDocs link
is_publishedBOOLEANWhether publicly visible
published_atTIMESTAMPTZFirst publish timestamp
install_countINTEGERTotal installs (incremented by increment_plugin_install_count())

plugin_versions

Every cursorist plugin deploy creates a new version row. Versions are immutable — assets are never overwritten in place.

ColumnTypeDescription
idUUID (PK)Version ID
plugin_idUUID (FK → plugins)Parent plugin
versionTEXTSemver string (e.g. 1.2.0), unique per plugin
changelogTEXTOptional release notes
manifestJSONBSnapshot of plugin.json at deploy time
is_prereleaseBOOLEANBeta/RC flag
is_yankedBOOLEANWithdrawn flag (hidden from install but not deleted)
yanked_reasonTEXTWhy it was yanked

plugin_assets

Individual files within a version — rules, skills, commands, MCP configs.

ColumnTypeDescription
idUUID (PK)Asset ID
version_idUUID (FK → plugin_versions)Parent version
asset_typeTEXTFile type: rule, skill, command, mcp, agent, hook
pathTEXTRelative file path (e.g. rules/project-standards.mdc), unique per version
content_rawTEXTFull file content
content_hashTEXTSHA hash for deduplication
size_bytesINTEGERFile size

plugin_channels

Named release channels (e.g. stable, beta). Each channel points to a specific version.

ColumnTypeDescription
plugin_idUUID (FK → plugins)Parent plugin
nameTEXTChannel name (unique per plugin)
version_idUUID (FK → plugin_versions)Currently pinned version
is_defaultBOOLEANWhether this is the default install channel

plugin_installs

Tracks which users have installed which plugins. Used for install counts, upgrade notifications, and analytics.

ColumnTypeDescription
user_idUUID (FK → users)Who installed
plugin_idUUID (FK → plugins)What was installed (unique per user)
version_idUUID (FK → plugin_versions)Installed version
channel_idUUID (FK → plugin_channels)Install channel
installed_viaTEXTHow: web, cli, mcp, deeplink
auto_updateBOOLEANWhether to auto-upgrade on new versions

plugin_favorites

User bookmarks for plugins.

ColumnTypeDescription
user_idUUID (FK → users)Who bookmarked
plugin_idUUID (FK → plugins)What was bookmarked (unique per user)

Utility Tables

api_keys

Personal API keys for CLI and MCP authentication.

ColumnTypeDescription
user_idUUID (FK → users)Key owner
nameTEXTDisplay name for the key
key_hashTEXTHashed key value (never stored in plain text)
expires_atTIMESTAMPTZOptional expiration

invitations

Team invitations sent by admins. Expire after 7 days by default.

ColumnTypeDescription
team_idUUID (FK → teams)Target team
inviter_idUUID (FK → users)Who sent the invite
emailTEXTRecipient email
github_usernameTEXTOptional GitHub handle
statusENUMpending, accepted, expired, cancelled
tokenTEXTUnique invite token
expires_atTIMESTAMPTZDefaults to 7 days from creation

site_notifications

Admin-created banners displayed on the welcome page.

ColumnTypeDescription
typeENUMinfo or alert
messageTEXTNotification content
is_activeBOOLEANWhether currently shown
expires_atTIMESTAMPTZOptional auto-hide time

site_config

Key-value configuration for feature flags and site settings. See Site Configuration for full details.

ColumnTypeDescription
keyTEXT (PK)Config key (e.g. maintenance_mode)
valueJSONBConfig value
descriptionTEXTHuman-readable explanation

Database Functions

FunctionPurpose
increment_plugin_install_count(plugin_uuid)Atomically increments a plugin's install count
publish_plugin_version(version_uuid)Marks a plugin as published and pins the version to the stable channel
get_latest_stable_plugin_version(plugin_uuid)Returns the newest non-prerelease, non-yanked version
update_updated_at_column()Trigger function that sets updated_at = NOW() on row update
add_owner_to_org_members()Trigger: auto-adds org creator as owner member
add_creator_to_team_members()Trigger: auto-adds org owner as team admin

Views

ViewDescription
user_organizationsJoins users → org_members → organizations for easy org listing
user_teamsJoins users → team_members → teams → organizations for easy team listing
published_pluginsJoins plugins → teams → organizations → users, filtered to is_published = TRUE

Row Level Security Summary

Every table has RLS enabled. Here is who can do what:

TableSELECTINSERTUPDATEDELETE
usersEveryone (public profiles)Own ID onlyOwn profile only
organizationsEveryoneAuthenticated usersOwner onlyOwner only
organization_membersOrg membersOrg ownerOrg ownerOrg owner
teamsOrg membersOrg ownerOrg ownerOrg owner
team_membersTeam membersTeam adminsTeam adminsTeam admins
pluginsPublished = everyone; unpublished = team membersTeam membersAuthor onlyAuthor or team admin
plugin_versionsVisible if parent plugin is visibleAuthor onlyAuthor onlyAuthor only
plugin_assetsVisible if parent version is visibleAuthor onlyAuthor onlyAuthor only
plugin_channelsVisible if parent plugin is visibleAuthor onlyAuthor onlyAuthor only
plugin_installsOwn installs onlyOwn onlyOwn onlyOwn only
plugin_favoritesOwn favorites onlyOwn onlyOwn onlyOwn only
api_keysOwn keys onlyOwn onlyOwn onlyOwn only
invitationsTeam membersTeam adminsTeam adminsTeam admins
site_notificationsActive ones = everyoneAdmins onlyAdmins onlyAdmins only
site_configEveryoneAdmins onlyAdmins onlyAdmins only