sdk
CLAUDE.md52 starsChanged 8 days agoMITView on GitHub
This is a lightweight monorepo of shared tooling for the Supabase client SDKs. Projects live as flat siblings under packages/, each with a single toolchain and no monorepo build tooling on top: The capability-matrix scripts live under packages/capability-matrix/. Run them from that directory: bun run aggregate uses GITHUB_TOKEN when it is set. Without one it falls back to anonymous requests, which GitHub limits to 60 per hour per IP address. To run a single test file:
- Reads credentials
In this repository3 other files it gives its agents.
- packages/postgrest-typegen/CLAUDE.mdCLAUDE.md
- packages/typegen/CLAUDE.mdCLAUDE.md
- capability-matrixSkill
The file
We split this CLAUDE.md into the rules it gives an agent
2 rules. About 0 are common, 0 are distinctive, and 2 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈0
Distinctive · estimate
This author's own choices. Worth a look.
2
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 104
Add the feature entry; ID must be {area}.{group}.{feature} and globally unique.
- Very specific: line 105
Run bun run validate — catches schema errors and duplicate IDs.
≈ “Common” is an estimate: at least 1 in 5 of the 26,980 CLAUDE.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
What This Repo Is
This is a lightweight monorepo of shared tooling for the Supabase client SDKs. Projects live as flat siblings under packages/, each with a single toolchain and no monorepo build tooling on top:
packages/capability-matrix/— the canonical feature registry for all Supabase client SDKs — not the SDKs themselves. It defines what features exist (name, description, grouping) across 7 client SDKs (JavaScript, Flutter, Python, Swift, C#, Go, Kotlin). SDKs declare compliance separately in their own repos viasdk-compliance.yamlfiles. The output is a static capability matrix website at https://supabase.github.io/sdk/ showing which features each SDK implements.packages/dart-symbol-extractor/— Dart public API symbol extractor used by the Dart compliance workflow.packages/go-symbol-extractor/— Go public API symbol extractor used by the Go compliance workflow.packages/postgrest-typegen/— introspects a PostgreSQL schema into theGeneratorMetadatacontract and generates PostgREST types for TypeScript, Go, and Python. See its ownCLAUDE.mdfor architecture and how postgres-meta and the CLI consume it.packages/typegen/: the language registry forsupabase gen types --lang.languagesmaps each name to a generator, either in-process (the four bundled in postgrest-typegen) or an external tool run in the user's project (Dart viadart run supabase_typegen). The CLI dispatches through it, so adding a language is a pull request here plus a CLI dependency bump. See its ownCLAUDE.md.
Commands
The capability-matrix scripts live under packages/capability-matrix/. Run them from that directory:
cd packages/capability-matrix
bun install # Install deps (first time / after changes)
bun test # Run full test suite
bun run typecheck # TypeScript check (strict, noEmit)
bun run format-and-lint # oxfmt --check + oxlint
bun run knip # Unused files, exports, and dependencies
bun run validate # Schema + structural checks (offline)
bun run validate:online # + reference checks against GitHub (needs GITHUB_TOKEN)
bun run report # Generate JSON parity report
bun run validate-compliance <file> # Validate a single SDK compliance file
bun run aggregate # Fetch all SDK compliance files via GitHub API
bun run build-site # Build HTML site (uses cached compliance data)
bun run build-site <compliance.json> # Build with specific compliance databun run aggregate uses GITHUB_TOKEN when it is set. Without one it falls back to anonymous requests, which GitHub limits to 60 per hour per IP address.
To run a single test file:
bun test test/schema.test.tsArchitecture
Data Flow
capabilities/*.yaml → validate (AJV schema) → aggregate (GitHub API fetches SDK compliance)
↓
generate-site.ts → static HTML (GitHub Pages)Key Directories (under packages/capability-matrix/)
capabilities/— YAML files, one per product area (auth, database, storage, realtime, functions, client). These are the source of truth for feature IDs and definitions.schema/capability-matrix.schema.json— JSON Schema that validates capability YAML files. Feature IDs must follow three-segment format:area.group_namespace.feature.specs/— Optional Markdown specs for individual features, atspecs/{area}/{group}/{method}.md. A spec is additive: it covers only what the SDK layer adds on top of the service's API spec, never the wire itself.src/— TypeScript source for validation, aggregation, and site generation.test/—bun:testsuite with fixtures intest/fixtures/.
Key Source Files
normalize-typedoc-cli.ts— merge form:--out <out.json> <in.json>…concatenates several TypeDoc JSONs (for monorepos)swift-parser.ts— line-by-line scanner (not AST); extractspublic/opensymbols from classes, structs, actors, enums, extensionspackages/dart-symbol-extractor/— sibling Dart package (Dart package namedart_symbol_extractor);dart run bin/extract.dart <sdk-root>; parses withoutpub getparse-ignore.ts—.sdk-parse-ignore(gitignore syntax) excludes paths from Swift parsing; TypeScript uses TypeDoc entrypoints insteadapi-check.ts/check-api-symbols.ts— blocking public API coverage logic + CLI;additionsmode diffs a PR against its base, whilefullmode statically audits one checkout
CI Workflows
capability-matrix-validate.yml— Runs on push to main, PRs, and nightly; Tier 1: schema/tests/typecheck/structural; Tier 2 (PRs + nightly): reference checks against GitHub. Its display name (Validate Capabilities) is referenced byrelease.yml'sworkflow_runtrigger — keep them in syncvalidate-sdk-compliance-<language>.yml— One reusable workflow per language (swift,javascript,python,dart), called by SDK repos; validatessdk-compliance.yamland applies itsapi_coveragepolicy.additions(the default) checks PR-only API changes against the base branch, whilefullchecks the complete current surface on PR, push, or dispatch events without a base checkout. Splitting per language avoids gating every step on alanguageinput. Forjavascript(the supabase-js pnpm monorepo) passtypedoc-packages— comma-separated package dirs, each with adocs:jsonscript that owns its TypeDoc entrypoints; the JS path installs with pnpm and merges all packages. Shared steps live in composite actions underpackages/capability-matrix/actions/sdk-compliance-*(-validate,-check-setup,-check-symbols,-check-drift), referenced through the_sdk-speccheckout (./_sdk-spec/packages/capability-matrix/actions/...) that the wrappers pin tojob.workflow_sha, so wrapper and action code always come from the same commit. The wrappers themselves must stay in.github/workflows/(a GitHub requirement forworkflow_call); keep them thin shims, since wrapper-only commits do not bump the capability-matrix component — force a release with aRelease-As: x.y.zcommit footer if one ever needs to ship alone. The Swift wrapper's check job is slow becauseswift package dump-symbol-graphcold-builds the whole package, so it takes arunnerinput (macOS label, defaultmacos-latest), skips pull requests that touch none ofpublic-api-pathsor the compliance file (theapi-pathsinput of the setup action), and caches compiled dependencies and base-commit symbols. Pull requests can read caches only from their own ref and the base branch, so a push to the default branch in additions mode (warm-cache) extracts once and saves them; pull requests only restore the build cachepostgrest-typegen-validate.yml: type check, lint, build and tests for postgrest-typegen, pluspostgrest-js type tests, which starts the postgrest-js fixture database from supabase-jsmaster, generates its types with the pull request's generator and runs postgrest-js's own type tests against them (SDK-1736). The second job is a required check onmain, which is whypull_requesttriggers the workflow without a path filter: achangesjob asks the API which files the pull request touches and the real jobs run only whenpackages/postgrest-typegenor the workflow changed, since a skipped job satisfies a required check while a workflow that never ran does notcapability-matrix-deploy-pages.yml— Fetches all SDK compliance data, rebuilds the site, and deploys to GitHub Pages (main push, daily cron, manual dispatch)release.yml— release-please for capability-matrix; postgrest-typegen and typegen run release-please from their own workflows, so three components are released in total. The repo root is deliberately not versioned anymore (the historicalvX.Y.Ztags up to 1.5.0 remain for consumers pinned to them). Both configs settag-separator: "/"because dependabot only recognizespackage/vX.Y.Ztags; releases before the switch used a-separator (capability-matrix-vX.Y.Z), which release-please still finds since it matches previous releases by component and version, not by separator.packages/capability-matrix(node, tagscapability-matrix/vX.Y.Z) gets a changelog and version bump only, nothing is published; its tags are what SDK repos pin the reusable compliance workflows at, since the compliance logic lives in the package. The symbol extractors are not release-managed at all.packages/postgrest-typegen(node, tagspostgrest-typegen/vX.Y.Z) additionally publishes: when its release is created, thepublish-postgrest-typegenjob builds with bun and publishes@supabase/postgrest-typegento npm via OIDC trusted publishing (no npm token; the trusted publisher must be configured on npmjs.com), and therelease-typegenjob then waits for npm to serve the version (it can lag the publish by a few minutes) and opens the typegen release pull request with the exact pin inpackages/typegenbumped, so one pull request both bumps the pin and releases typegen. release-please only builds a release pull request from commits already on its target branch, so the job commits thefix(typegen):pin bump to a staging branch, runs release-please against that branch, retargets the resulting pull request tomain, deletes the staging branch and closes any other open typegen release pull request it supersedes. release-please tags it on merge because it matches merged release pull requests by label, title and the component in the head branch name, not by the branch they were opened against.packages/typegen(node, tagstypegen/vX.Y.Z, configrelease-please-config.typegen.json, workflowrelease-typegen.yml) follows the same on-demand pattern and publishes@supabase/typegen; its manifest starts at0.0.0so the first release is0.1.0. On-demand means both workflows run release-please only onworkflow_dispatchor on a push that changes their manifest file, which happens only when a release PR merges; merging ordinaryfix:/feat:commits into the package opens no release PR until someone dispatches the workflow- bun installs through
oven-sh/setup-bun(SHA-pinned,bun-version: latest), the same convention supabase-js uses. The runtime version deliberately floats; only the action itself is pinned, and dependabot'sgithub-actionsgroup keeps that SHA current dependabot.yml— every JavaScript package commits abun.lock, so a singlebunentry globs/packages/*. Do not move them back to thenpmecosystem: it rewritespackage.jsonwithout touchingbun.lock, which leaves the lockfile stale and fails everybun install --frozen-lockfilestep.oxfmtis ignored there on purpose: postgrest-typegen formats its generated output with it, so a bump changes generated code and must be done manually in all JavaScript packages together.@supabase/postgrest-typegenis ignored too, since the postgrest-typegen release workflow bumps it in the typegen release pull request
Feature IDs
Feature IDs use three segments: {area}.{group}.{method} (e.g., auth.sign_in.sign_in_with_password, storage.file_buckets.create_file_bucket). The area must match the file's area field. IDs must be globally unique across all capability files.
SDK Compliance Format
Each SDK repo hosts a sdk-compliance.yaml at a known path. Format:
sdk: javascript
features:
auth.sign_in.sign_in_with_password: implemented
auth.mfa.enroll:
status: partially_implemented
note: "TOTP only"
symbols:
- GoTrueClient.mfaEnroll # optional: public symbol names implementing this feature
storage.file_buckets.upload: not_implementedValid status values: implemented, partially_implemented, not_implemented, not_applicable.
The symbols field is optional but enables the public API check in CI: when a PR adds a new public symbol not listed under any symbols entry, the check fails and prompts the author to register it.
Adding a Feature
- Pick or create a YAML file in
packages/capability-matrix/capabilities/for the relevant area. - Add the feature entry; ID must be
{area}.{group}.{feature}and globally unique. - Run
bun run validate— catches schema errors and duplicate IDs. - Optionally add a spec at
packages/capability-matrix/specs/{area}/{group}/{feature}.md, followingspecs/TEMPLATE.md: only what an SDK implementer cannot get from the API spec, written as a contract that names no SDK and is precise enough that two implementers would build the same thing. See "Adding a spec file" inCONTRIBUTING.mdfor the three tests every sentence passes before a PR.
Commit Style
Conventional commits: feat:, fix:, docs:, chore:, refactor:, test:, ci:. Scope is the registry area for capability and spec changes (feat(auth), docs(storage)), the package directory name for a package's own tooling or docs (fix(postgrest-typegen)), and absent for anything outside a package. A new capability and its spec go in one feat commit. A spec on its own is docs. Use feat(<area>)!: for breaking changes to feature IDs (which affect all SDK compliance files referencing those IDs).
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

