Skip to content
Security
Skill

/stash-supabase

Integrate CipherStash encryption with Supabase using @cipherstash/stack-supabase. Covers the encryptedSupabase wrapper over native EQL v3 column domains, transparent encryption/decryption on insert/update/select, encrypted scalar filters (eq, gt/gte/lt/lte, in, or), ordering on

BOOST
From plugin
stack
16116 skills1 command
Install
$ npx -y skills add cipherstash/stack --skill stash-supabase --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/stash-supabase

Context preview

The summary Claude sees to decide when to auto-load this skill.

Integrate CipherStash encryption with Supabase using @cipherstash/stack-supabase. Covers the encryptedSupabase wrapper over native EQL v3 column domains, transparent encryption/decryption on insert/update/select, encrypted scalar filters (eq, gt/gte/lt/lte, in, or), ordering on

SKILL.md

stash-supabase.SKILL.md
name: stash-supabase
description: Integrate CipherStash encryption with Supabase using @cipherstash/stack-supabase. Covers the encryptedSupabase wrapper over native EQL v3 column domains, transparent encryption/decryption on insert/update/select, encrypted scalar filters (eq, gt/gte/lt/lte, in, or), ordering on encrypted columns, EQL 3.0.5 PostgREST query-domain limitations, identity-aware encryption, and the complete query builder API. Use when adding encryption to a Supabase project, querying encrypted columns, or building secure Supabase applications.

CipherStash Stack - Supabase Integration

Guide for integrating CipherStash field-level encryption with Supabase using the `encryptedSupabase` wrapper over native EQL v3 column domains. The wrapper provides transparent encryption on mutations and decryption on selects, with support for equality, range, and ordering.

> **Naming note.** `encryptedSupabase` is the current EQL v3 factory. > `encryptedSupabaseV3` remains as a `@deprecated`, type-identical alias, so > existing imports keep working — prefer `encryptedSupabase` in new code. The > old EQL v2 authoring wrapper (`encryptedSupabase({ encryptionClient, > supabaseClient }).from(table, schema)`) has been **removed** — see > "Legacy: EQL v2" at the end.

When to Use This Skill

  • Adding field-level encryption to a Supabase project
  • Querying encrypted data with Supabase's query builder (eq, gt, in, or, etc.)
  • Understanding encrypted JSON query limitations in PostgREST
  • Inserting, updating, or upserting encrypted data
  • Using identity-aware encryption (lock contexts) with Supabase
  • Building applications where sensitive columns need encryption at rest and in transit

> **On a managed AI platform — Lovable, v0, Bolt, Replit — read `stash-managed-platforms` first.** Two things there are decided before anything on this page applies: server code runs on an edge runtime, so it needs `@cipherstash/stack/wasm-inline` (`@cipherstash/protect` is the deprecated predecessor and its native module will not load — that dead end has cost an agent a whole turn), and the database role is not `postgres`, which changes how EQL gets installed. `encryptedSupabase` can be constructed inside an edge runtime, but only from the `@cipherstash/stack-supabase/wasm-inline` entry and only with declared `schemas` — introspection is what needs a Postgres connection, and declaring your tables is what skips it. Step 5 of Setup has the call shape.

> **What survives PostgREST, in one line** (the full treatment is under [Query behaviour on encrypted columns](#query-behaviour-on-encrypted-columns), a long way down): `eq` / `neq` / `in` / `match()` and the range filters `gt` / `gte` / `lt` / `lte` **do** work on capable domains, and so does `order()` on OPE-backed ordering columns. Encrypted free-text `matches()` and encrypted-JSON `contains()` / `selectorEq()` / `selectorNe()` **do not** — they need `eql_v3.query_*` casts PostgREST cannot emit, and the wrapper fails fast rather than returning wrong rows. Agents guess wrong in both directions on this, so don't infer it; for the predicates that don't survive, use Drizzle, Prisma Next, or SQL in an RPC.

Installation

npm install @cipherstash/stack @cipherstash/stack-supabase @supabase/supabase-js

> **Version note:** `npx stash init` is the preferred install path — it pins > every `@cipherstash/*` package to the versions matching your CLI release. > If you install manually as above, verify what actually resolved > (`node -p "require('@cipherstash/stack/package.json').version"`): bare > dist-tag installs can lag behind a release, and `stash init` will warn on > the version skew.

The Supabase integration ships as its own first-party package, `@cipherstash/stack-supabase`, which depends on `@cipherstash/stack`. Install both.

Setup

**Credentials first:** for local development run `npx stash init` (the agent-assisted flow — auth, schema, and database end to end) or `npx stash auth login` (device code flow; no environment variables needed). CI and production use the `CS_*` machine-credential environment variables — see the `stash-encryption` skill's Configuration section. Mint them from your device session with `npx stash env --name <name>` (no dashboard copy-paste); this is also how **Supabase Edge Functions** get credentials in local dev — `supabase functions serve` runs in a container that cannot see `~/.cipherstash`, so write the vars to a file with `stash env --name edge-dev --write` and pass `--env-file`, or `supabase secrets set` them for deploys.

> **One credential set per environment — but what must match between writers > and query readers is the keyset, not the credential string.** Index terms > come from a per-*keyset* key, so any client bound to the keyset produces > matching terms. Decrypt is looser — it follows each payload's keyset and > needs only a grant — so a reader granted the writer's keyset but bound to > a different one decrypts fine while its searches silently return zero > rows. `stash-zerokms` is canonical for keyset scoping, `stash-auth` for > credentials. Inside an > Edge Function (Deno, no native modules) the wrapper comes from > `@cipherstash/stack-supabase/wasm-inline` — step 5 below. For encryption > without the Supabase wrapper it is `@cipherstash/stack/wasm-inline`, see the > `stash-edge` skill; SQL written by hand in a migration or RPC is covered by > `stash-postgres`.

1. Install EQL v3 on the database

Install it as a **migration**, not directly:

stash eql migration --supabase   # writes supabase/migrations/<timestamp>_cipherstash_eql.sql
supabase db reset                # local — replays every migration
supabase db push                 # remote/linked project

> A bare `supabase migration up` applies to the **local** database. The remote > forms are `supabase db push` and `supabase migration up --linked`.

> ⚠️ **Do not use `stash eql install --supabase` on a project with a local > `supab

Read more
Ships withstack

Searchable, application-level encryption for building privacy-first apps

Get the whole plugin

Other skills on stack.

stash-auth
Skill

stash-auth

How a CipherStash client authenticates — the canonical skill for credentials, auth strategies, and lock context. Covers the…

stash-cli
Skill

stash-cli

Drive CipherStash setup and encryption migrations through the `stash` CLI — `init`, `plan`, `impl`, `status`, `auth login`, `eql…