sixty

Client-Agent

Supabase

Der einzige Agent, der weiß, was der Endpunkt *ist*, statt was er gekostet hat — er kann also eine langsame Abfrage von einer Regel unterscheiden, die eine abgelehnt hat.

Paket
@sixty-sh/supabase auf npm
läuft auf
Neben dem Browser-Agenten, in einem Projekt, dessen Backend Supabase ist.
Quellcode
sixty-sh/sixty-supabase

Installation

For a frontend with no server of your own to deploy: runs entirely in the browser with a public, origin-pinned key. If the project has any server, use browser or node.

Die Installation ist als Prompt für den Coding-Agenten geschrieben, den du ohnehin offen hast, nicht als Checkliste für dich. Das ist Absicht: sie benennt, was am Ende wahr sein muss, statt welche Dateien zu bearbeiten sind — denn wohin der Code gehört, hängt vom Framework ab, und ihn an die falsche Stelle zu setzen scheitert lautlos. Ein Agent kann dein Repository lesen und das herausfinden; ein Absatz auf einer Dokumentationsseite kann es nicht.

Denselben Text liefert install_sixty über den MCP-Server zurück, und den serviert der Collector unter /v1/setup?kind=lovable. Es gibt genau eine Kopie davon.

die vollständige Supabase-Installation
Add sixty.sh performance monitoring to this app. It measures Supabase query
shape, page speed, stuck loading states and browser errors, and reports
anonymously.

Before anything else: does this project run a server of its own? A Lovable
app often grows one — an API route, a serverless function, an Express or
FastAPI backend added later, a Supabase edge function you deploy. If it has
one, STOP and ask for the "browser" install instead, or the "node" or
"python" one if the server holds logic worth measuring. Those keep the key
server-side behind a proxy and can measure the server as well as the page.
This install is for the case where the frontend is genuinely the only code
you deploy, and it trades a world-readable key for that.

If that is this project, work out which shape it is, because it decides where
the code goes and there is no error if you get it wrong — it just silently
never runs:

  A. Client-only Vite SPA. There is a createRoot(...) call in a file like
     src/main.tsx and no server entry.
  B. Server-rendered framework app — React Router v7 framework mode, Remix,
     or similar. Signs: an entry.client.tsx / entry.server.tsx pair, a
     root.tsx, a hydrateRoot(...) call, or a routes.ts.

Then:

1. Add two dependencies: @sixty-sh/supabase and @sixty-sh/browser.

2. Call init() from "@sixty-sh/browser" exactly once, in the browser.

      init({ key: "sixty_pk_YOUR_KEY" })

   In shape A, module scope in the app entry is fine.
   In shape B it MUST go in the client entry (entry.client.tsx), after
   hydration. Do not put it in a shared module that the server also
   evaluates: there it runs during server rendering, finds no window,
   returns null, and reports nothing at all — with no error to tell you.

3. Find where the Supabase client is created. Search the repository for
   "createClient(" rather than guessing a path — it is often in
   src/integrations/supabase/client.ts but in this kind of project it may be
   anywhere. Then, at module scope in that same file:

      import { withSixty } from "@sixty-sh/supabase"
      withSixty(supabase, { key: "sixty_pk_YOUR_KEY", service: "my-app" })

   Use the client that already exists. withSixty patches the PostgREST
   prototype and returns the same object it was given, so it instruments every
   query in the app without replacing the export.

Constraints — correctness requirements, not style preferences:

- Do NOT create a second Supabase client. There must still be exactly one.
- Do NOT edit vite.config.ts and do NOT add a Vite plugin.
- Do NOT change any existing query, component, or hook. This is
  instrumentation only; no behaviour should change.
- The key above is PUBLIC by design: write-only, pinned to one service, and
  refused from any origin it does not list. Paste it literally. Do not move it
  into an environment variable or a secret.
- Do NOT add any analytics library, user id, session id, or cookie. This agent
  is deliberately anonymous and must stay that way.

When you are done, tell me which shape you found and which files you changed,
then publish the app. Findings need two published releases with traffic under
each before anything can be compared.

Er braucht einen öffentlichen Schlüssel — an deine Origins gebunden, weil eine Anwendung ohne eigenen Server keinen Ort hat, an dem ein Geheimnis leben könnte.

Was er misst

SignalEinheitwas es bedeutet
errorserror ratea larger fraction of calls are throwing
new_erroroccurrencesan error that did not occur in the previous release
latencyms per callthis operation takes longer end to end than it used to
silent_empty—The query runs and succeeds, and returns no rows where it used to return plenty. Nothing reports an error, so the page just renders blank — this is what a broken permission rule looks like from the outside.
auth_failures—The server is turning these away on permission grounds rather than failing. People see an empty page or a save that quietly does nothing.

Fehler, die er benennen kann

Keine Signale. Das sind die Klassen, die er einem Fehler gibt — und genau die machen den Unterschied zwischen „ein Aufruf ist fehlgeschlagen“ und „eine Regel hat ihn abgelehnt“.

rls_deniedA row-level security policy refused the statement (Postgres 42501). It reaches the browser as an empty list and your logs as nothing at all.
schema_missingA column, table, relationship or function the code expects is not in the database.
constraint_violatedA write was rejected by a database constraint.
jwt_expiredA session token was expired or invalid where one was required.
realtime_duplicate_subscriptionOne topic subscribed concurrently three times or more — an effect with no teardown, seen from the wire.
realtime_channel_errorA channel reported CHANNEL_ERROR or TIMED_OUT instead of subscribing.

Wo er sich einhängt

  • supabase-js — PostgREST-Aufrufe, Realtime-Kanäle und Auth, dort instrumentiert, wo sie gemacht werden.
  • Vite — Ein Plugin, für Projekte, die damit gebaut werden.

Datenbanken

  • PostgREST — Die Anfrage beschreibt die Abfrage, also sind die Tabelle, die Filter und der Fehlercode auch ohne Statement lesbar.

Was nur dieser kann

  • Ein Name für den Fehlschlag — Jeder andere Agent kann sagen, dass ein Aufruf fehlgeschlagen ist. Dieser kann sagen, dass eine Regel ihn abgelehnt hat, dass eine Spalte fehlt oder dass das Token abgelaufen war — weil eine PostgREST-Anfrage die Abfrage beschreibt, statt bloß etwas zu kosten.
  • Realtime ebenso wie Lesevorgänge — Kanäle, die Fehler werfen, in ein Timeout laufen oder dreifach abonniert werden, weil ein Effekt kein Aufräumen hat.

Was er nicht kann

  • Das ist eine Ergänzung zum Browser- oder Lovable-Agenten, kein Ersatz dafür. Es erklärt Supabase-Fehler; es misst nicht die Seite.
  • Ein Projekt ohne eigenen Server benutzt einen öffentlichen, an das Origin gebundenen Schlüssel. Wenn daraus eine API-Route oder eine Edge Function gewachsen ist, nimm die Browser- oder Node-Stufe — der Schlüssel bleibt serverseitig, und der Server wird gleich mitgemessen.

Konfiguration

Jeder Agent liest dieselben vier Variablen, und DRIFT_* antwortet weiterhin überall dort, wo SIXTY_* es tut — das Produkt wurde umbenannt, und dieser Name ist nicht unserer, um ihn aus fremden Deployments zu entfernen.

SIXTY_API_KEYOhne sie bleibt der Agent untätig und sagt das auch. Er rät nie, versucht es nie erneut gegen einen unbekannten Endpunkt, und wirft nie.
SIXTY_SERVICEWie dieser Dienst heißen soll. Standardmäßig der Projektname, wo einer lesbar ist.
SIXTY_RELEASEDie wichtigste. Wird auf Vercel, Render, Railway, Fly, Heroku und GitHub Actions automatisch abgeholt; überall sonst setze sie auf den Commit-SHA. Ohne sie landet jede Messung in einem einzigen namenlosen Eimer, und kein Vergleich ist je möglich.
SIXTY_ENDPOINTWohin gemeldet wird. Standardmäßig http://localhost:4319, was auf einem Laptop richtig ist und in dem Moment falsch, in dem die Anwendung jemand anderem ausgeliefert wird.

Der Rest — Flush-Intervall, Sample-Rate, was instrumentiert wird — steht im README des Pakets selbst, wo es wahr bleiben kann, während sich der Agent verändert.

Der Supabase-Agent von sixty — was er misst und wie man ihn installiert