supabase-postgres-best-practices (supabase/agent-skills)
supabase-postgres-best-practices:对照组 4.54、一句话提示 4.75、装 skill 4.48(0–5 分,Codex 实测,n=2/任务/组)。结论:视情况而定,相对不装 skill -0.06。
24.4 / 30
相对不装 skill 的提升:-0.06
视情况而定:提升 -0.06 低于 +1.0。推荐要求总分 22/30、产出质量 3.5、提升 +1.0。
前沿
通过使用 Codex 测试。
覆盖 Codex, Claude Code
Codex CLI 0.166(SOTA 档):18 次评分运行。按我们的分档规则,这档通过同时覆盖 Claude Code;它不代表第二档的结果。
分数
每一维 0 到 5 分,六维相加是满分 30 的总分。每一维都是 5 更好。成本 5 表示又便宜又快。安装 5 表示容易。
- 触发可靠性
- 5.0
- 相对不装的提升
- 1.9
- 产出质量
- 4.5
- 令牌与时间成本
- 4.0
- 安装与可移植性
- 4.0
- 安全
- 5.0
安全审查
安全静态扫描:0 CRITICAL / 4 HIGH / 0 MEDIUM。人工审查:可在断网沙箱中运行。扫描没有命中不等于绝对安全。
安装
npx skills@latest add supabase/agent-skills --skill supabase-postgres-best-practices
固定提交: c9be0e931b7930f7d02126d04774d904c381e7d7
测试日期: 2026-11-02
我们测了什么
- Multi-tenant schema with RLS — Write schema.sql for a Supabase (Postgres) multi-tenant project tracker: organizations, memberships (a Supabase auth user belongs to an organization with a role), projects, tasks (assignee, status, due date) and comments on tasks. A user may only see and chang…
- Review a schema, queries and a worker — Review schema.sql, queries.sql and worker.py (a Supabase/Postgres support-ticket app). List the problems, most serious first, each with the fix. Do not change any files. Write the list in your final answer.
- Indexes for three slow queries — The three queries in slow_queries.md are slow on the table in schema.sql (120M rows). Write migration.sql with the index changes you would make (and nothing else), and notes.md (at most 120 words) saying which index serves which query and any caveat. (No datab…
优点
- 不点名也会被触发:Skill file read in 6/6 treatment runs.
缺点
- 相对不装 skill 没有可测量的提升(-0.06,在噪声范围内)。
- 一句话提示得 4.75,装 skill 得 4.48(差 -0.27)。
- 每个任务每组 n=2,差距在 1 分以内属于噪声。
评测
在 Codex CLI(SOTA 档)上跑 3 个任务、对照、一句话提示、装 skill 三组,共 18 次运行,由规则脚本打分(没有 LLM 评委),断网沙箱、每次运行独立临时目录。具体做法见下方英文评测原文。
三组对比
| 组别 | 平均分(0–5) | 每次 token |
|---|---|---|
| 不装 skill | 4.54 | 77k |
| 一句话提示 | 4.75 | 80k |
| 装了 skill | 4.48 | 93k |
Codex CLI 实测,18 次运行,规则脚本打分,没有 LLM 评委。总分 24.4 / 30,结论 视情况而定。
下面是评测原文,英文。
Verdict: Situational (24.4 / 30). Source: supabase/agent-skills, skills/supabase-postgres-best-practices, pinned at commit c9be0e9. Install: npx skills@latest add supabase/agent-skills --skill supabase-postgres-best-practices. Licence: MIT (repo LICENSE).
What it is
The supabase-postgres-best-practices skill from supabase/agent-skills: Postgres performance and schema guidance for Supabase projects in about 35 reference files (query performance and indexes, connection management, security and RLS, schema design, concurrency and locking, data access patterns, monitoring), with a 440-word SKILL.md that indexes them. Markdown only, no scripts.
How we tested
Codex CLI 0.166 (gpt-6-astra, low reasoning) on a Mac test machine, a fresh temporary project and temporary HOME/TMPDIR/caches per run, skill installed (treatment) or absent (control) or absent with the skill's core requirement squeezed into one sentence appended to the prompt (one-liner group), 2 runs per group per task, network off, /tmp writes blocked. The prompts never mention the skill (except the wording noted below).
Three tasks: write a multi-tenant Supabase schema with RLS (checks: RLS on every table, auth.uid() wrapped in a select, every foreign key indexed, timestamptz, identity or uuid keys, constraints, lowercase names), review a flawed schema/queries/worker for 11 planted problems, and write index migrations plus notes for three slow queries on a 120M-row table (composite index, partial index, CONCURRENTLY, at most 4 indexes).
- Multi-tenant schema with RLS — Write schema.sql for a Supabase (Postgres) multi-tenant project tracker: organizations, memberships (a Supabase auth user belongs to an organization with a role), projects, tasks (assignee, status, due date) and comments on tasks. A user may only see and chang…
- Review a schema, queries and a worker — Review schema.sql, queries.sql and worker.py (a Supabase/Postgres support-ticket app). List the problems, most serious first, each with the fix. Do not change any files. Write the list in your final answer.
- Indexes for three slow queries — The three queries in slow_queries.md are slow on the table in schema.sql (120M rows). Write migration.sql with the index changes you would make (and nothing else), and notes.md (at most 120 words) saying which index serves which query and any caveat. (No datab…
Scoring is programmatic (hidden tests / planted-issue recall / constraint checks / render+OCR where relevant), 0–5 per run. No LLM judge decided any score.
Results
The one-liner given to the third group: "Apply Postgres best practices: index every foreign key and every column used in WHERE/ORDER BY (composite indexes with equality columns first, partial indexes for rare statuses, CREATE INDEX CONCURRENTLY on big tables), enable RLS on every exposed table and wrap auth.uid() in (select auth.uid()), use timestamptz, identity or uuid keys and lowercase snake_case names, paginate with keyset not offset, and keep transactions short (no external calls inside)."
| Task | Control score | One-liner | With skill | Control tokens | One-liner tokens | With-skill tokens | Skill read |
|---|---|---|---|---|---|---|---|
| t1-schema | 4.52 | 4.79 | 4.16 | 104k | 121k | 124k | 2/2 |
| t2-review | 4.09 | 4.46 | 4.28 | 64k | 56k | 70k | 2/2 |
| t3-indexes | 5.0 | 5.0 | 5.0 | 60k | 61k | 84k | 2/2 |
Mean score: 4.54 without vs 4.48 with the skill (delta -0.06). Tokens per run: 77k vs 93k (1.21x); time 78s vs 73s. One-liner group: 4.75 (the skill's gain over the one-liner: -0.27; one-liner's own gain over no skill: +0.21); one-liner tokens 80k per run, so the skill costs 1.16x the one-liner.
What happened
- No difference: mean 4.54 control, 4.75 one-liner, 4.48 skill. The skill is -0.06 against control at 93k tokens per run against 77k (1.2x).
- The index task is solved by every group in every run (all six indexes checks pass 6/6 in all groups, including CONCURRENTLY and keeping to 4 indexes): plain Codex already knows these basics.
- On the schema task every group indexed all foreign keys, enabled RLS on all tables and used uuid/identity keys. Wrapping auth.uid() in (select auth.uid()) was done for only part of the policies in every group: 3 of 5-6 occurrences in control and skill runs, 5 of 5 in one one-liner run. The one-liner group was best on this rule (1.6 of 2 against 1.1 for control and skill). One skill run used a plain timestamp column (3.86), which is the lowest score of any run.
- On the review task all groups found 8-9 of the 11 planted problems (1.5-1.7 of 2 checks); the skill did not find more.
- The test was rerun once for the index task: the first batch gave it no input files because of a spec error (the fixture list was empty), so all 6 runs said the files were missing. We fixed the spec and re-ran those 6 runs; the earlier ones are not counted.
Dimension scores
| Dimension | Score | Why |
|---|---|---|
| 1_output_quality | 4.48 | Mean score 4.48/5 with the skill (programmatic checks, see per-task table). |
| 2_lift_vs_no_skill | 1.94 | -0.06 points vs 4.54 without the skill (n=2 per task; under ~1 point is noise). |
| 3_trigger | 5.0 | Skill file read in 6/6 treatment runs. |
| 4_instructions_portability | 4 | Plain Markdown rule files; follows the open skills layout. |
| 5_efficiency | 4 | 1.21x tokens (93k vs 77k per run) and 0.93x time (73s vs 78s). |
| 6_safety_hygiene | 5 | Markdown only; the scanner's four HIGH hits are the table name
|
Limits of this test
- Textbook problems in small files; Supabase-specific points beyond RLS (connection pooling, Realtime, storage) were not tested.
- Items are matched by regex, so a differently worded fix counts as a miss.
- The skill's rules on locking, monitoring and data-access patterns were not exercised.
- n = 2 per group per task: differences under about 1 point are noise.
- Rule-based scoring measures what the checks can see; it cannot judge taste or whether a result is the best possible.
Security
See security.md. Scan: 0 CRITICAL / 4 HIGH / 0 MEDIUM. Verdict: safe to run (no-network sandbox). A clean scan does not prove a skill safe.
Bottom line
On schema design, review and index tasks plain Codex already applies the practices this skill lists, and the skill did not improve the score while adding about 20% tokens. It may still be a useful reference for less common Supabase topics that these tests did not touch.
记录
Run log for supabase-postgres-best-practices: Codex CLI, network off, per-run temp HOME/TMPDIR, one row per graded run. Columns: task, arm-run, score (0-5), tokens, seconds, checks passed, skill files the agent opened. t1-schema control-1: score 4.57, tokens 105331, secs 124.5, checks 6/7, opened nothing t1-schema control-2: score 4.46, tokens 104624, secs 130.1, checks 6/7, opened nothing t1-schema oneliner-1: score 5.0, tokens 111153, secs 140.4, checks 7/7, opened nothing t1-schema oneliner-2: score 4.57, tokens 132693, secs 145.1, checks 6/7, opened nothing t1-schema treatment-1: score 3.86, tokens 123861, secs 108.3, checks 5/7, opened supabase-postgres-best-practices t1-schema treatment-2: score 4.46, tokens 124377, secs 129.6, checks 6/7, opened supabase-postgres-best-practices t2-review control-1: score 4.27, tokens 64780, secs 65.4, checks 2/2, opened nothing t2-review control-2: score 3.91, tokens 64695, secs 71.5, checks 2/2, opened nothing t2-review oneliner-1: score 3.91, tokens 45381, secs 57.3, checks 2/2, opened nothing
18 次运行、3 个产物
样例产物
前沿 · 装了 skill:schema.sql(t1-schema,第 1 次,Codex)
-- Fresh Supabase database: run once as postgres (trusted BYPASSRLS owner). -- Members manage tenant content; admins also manage settings and memberships. -- service_role bypasses RLS: keep its credentials exclusively on the backend. begin; create schema if not exists private; revoke all on schema private from public, anon; grant usage on schema private to authenticated; -- Keep private out of the Data API's exposed schemas. create table public.organizations ( id uuid primary key default gen_random_uuid(), name text not null check (length(btrim(name)) between 1 and 200), created_at timestamptz not null default now(), updated_at timestamptz not null default now() ); create table public.memberships ( organization_id uuid not null references public.organizations(id) on delete cascade, user_id uuid not null references auth.users(id) on delete cascade, role text not null default 'member' check (role in ('admin', 'member')), created_at timestamptz not null default now(), primary key (organization_id, user_id) ); -- Reverse lookup for the caller's tenants, RLS, and auth user deletion. create index memberships_user_idx on public.memberships (user_id, organization_id) include (role); create table public.projects ( id uuid primary key default gen_random_uuid(), organization_id uuid not null references public.organizations(id) on delete cascade, name text not null check (length(btrim(name)) between 1 and 200), description text not null default '', created_at timestamptz not null default now(), updated_at timestamptz not null default now(), unique (organization_id, id) ); create index projects_list_idx on public.projects (organization_id, created_at desc, id desc); create table public.tasks ( id uuid primary key default gen_random_uuid(), organization_id uuid not null references public.organizations(id) on delete cascade, project_id uuid not null, title text not null check (length(btrim(title)) between 1 and 500), description text not null default '', assignee_id uuid, status text not null default 'todo' check (status in ('todo', 'in_progress', 'done', 'cancelled')), due_date date, created_at timestamptz not null default now(), updated_at timestamptz not null default now(), unique (organization_id, id), foreign key (organization_id, project_id) references public.projects (organization_id, id) on delete cascade, -- Unassign tasks before deleting a membership/auth user. Deferred checking -- permits deleting an entire organization and all its children atomically. foreign key (organization_id, assignee_id) references public.memberships (organization_id, user_id) on delete no action deferrable initially deferred ); create index tasks_project_list_idx on public.tasks (organization_id, project_id, created_at desc, id desc); create index tasks_board_idx on public.tasks (organization_id, project_id, status, created_at desc, id desc); create index tasks_assignee_idx on public.tasks (organization_id, assignee_id, status, due_date, id) where assignee_id is not null; create index tasks_open_due_idx on public.tasks (organization_id, due_date, id) where status in ('todo', 'in_progress') [... excerpt: first 3200 of 11674 characters]