clerk/clerk-monorepo
>- Work effectively in the clerk/javascript SDK monorepo. Use when setting up the repo, building / testing / running a package, deciding which of the @clerk/* packages to change, writing changesets, conventional commits, or PRs, or checking whether a change is a breaking change to clerk-js or ui. Covers the pnpm + turbo dev loop, the package map, and the repo's hard rules. AGENTS.md is the authority on the rules; this skill is the how-to layer that points back to it.
npx skills add https://github.com/clerk/javascript --skill clerk-monorepo
This is Clerk's JavaScript SDK monorepo: 24 packages (21 published @clerk/* plus the private
@clerk/msw, @clerk/headless, and @clerk/swingset) managed with pnpm
workspaces and Turborepo. Read this before building, testing, committing, or touching anything
under packages/.
AGENTS.md (repo root) is the canonical source of truth for the hard rules. This skill restates
those rules in actionable form and links back to it. If a rule here ever disagrees with AGENTS.md,
AGENTS.md wins, and the discrepancy should be fixed here.
The order matters more than the commands. Do them in sequence:
>=24.15.0 (pinned in .nvmrc). nvm use if you have nvm. Wrong Node version is thesingle most common cause of cryptic "cannot find module @clerk/..." build errors.
corepack enable before installing. The preinstall hook runs only-allow pnpm; npm/yarnare hard-blocked. Corepack pins the right pnpm (>=10.33.0).
pnpm install from the repo root (never a subdirectory). It is a workspace; installing froma package dir leaves cross-package links broken.
pnpm build before anything else. Packages depend on each other's built dist/ + .d.ts.Skipping this makes dev, tests, and the editor's types all report phantom errors.
pnpm dev to start watch mode.Full sequence, the 11 footguns, and the internal integration-test / 1Password setup live in
references/setup-and-footguns.md.
The ~10 packages people touch most. Full 24-package table, the dependency pyramid, and the complete
"change X, touch Y" routing are in references/package-map.md.
| Package | You change it when... |
| ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| @clerk/shared | Utilities used everywhere (storage, events, React helpers). Most-depended-on; changes fan out to ~20 packages. Types live here too (@clerk/shared/types). |
| @clerk/backend | Server-side: JWT verification, the Backend API REST client, webhooks. Used by every framework adapter. |
| @clerk/clerk-js | ⚠️ The browser runtime loaded via script tag. Backwards-compat sensitive (see rules). |
| @clerk/ui | ⚠️ The React components powering the hosted sign-in / sign-up UI. Backwards-compat sensitive. |
| @clerk/react | Shared React hooks/context (useAuth, useUser, ...) consumed by the React-based adapters. |
| @clerk/nextjs | Next.js SDK: middleware, route handlers, server components. |
| @clerk/express | Express middleware and server helpers. |
| @clerk/expo | React Native / Expo SDK. |
| @clerk/localizations | UI translation strings (consumed by ui). |
| @clerk/testing | E2E helpers for consumers (Playwright / Cypress). |
> Heads-up: packages/ may contain stale leftover dirs (types, remix, themes, elements, ...)
> with only build artifacts and no package.json. Those are removed packages, not active ones. The
> authoritative list is the git-tracked packages/*/package.json files.
# Build one package (and its deps, via turbo ^build)
pnpm turbo build --filter=@clerk/nextjs
# Watch subsets instead of everything
pnpm dev:fe-libs # clerk-js + ui + shared
pnpm dev:js # clerk-js only
pnpm dev:sandbox # rspack sandbox for previewing UI components
# Run one package's unit tests (builds the package and its deps first)
pnpm turbo test --filter=@clerk/backend
# Faster, after a full build, for tight iteration:
pnpm --filter @clerk/backend test
# Run a single test file (vitest matches by filename substring). No `--` before the path:
# pnpm forwards a literal `--` into the script and vitest then ignores the filter.
pnpm --filter @clerk/shared test path/to/file.test.ts
# @clerk/backend runs a multi-runtime suite (run-s), so target one runtime for a single file:
pnpm --filter @clerk/backend test:node path/to/file.test.ts
# Quality gates (run before pushing; CI runs equivalent checks)
pnpm lint
pnpm format # workspace packages plus root files, docs/, integration/, scripts/
pnpm prettier --write '.claude/**/*.md' # pnpm format does not cover .claude/; format skill files this way
# Changesets — write the file, don't run the CLI (both scripts are interactive prompts)
pnpm changeset status --since=origin/main # what CI checks; run this to verify
Write .changeset/<descriptive-name>.md directly, in the repo root .changeset/ (never
packages/<pkg>/.changeset/). Package change:
---
'@clerk/nextjs': patch
---
Remove the redundant `https://*.client.protect.clerk.com` source from CSP headers generated by `clerkMiddleware()`.
Repo/tooling-only or private-package-only change — the file is exactly two delimiters, nothing else:
---
---
@clerk/swingset, @clerk/msw, and @clerk/headless are private and never appear in a changeset;
every other packages/* entry publishes, including @clerk/ui and @clerk/clerk-js. Bump
selection, which packages to list, body-writing rules, and the major-version gate are in
references/changesets.md.
Test runner differs by package (shared, clerk-js, most adapters use vitest; backend runs a
multi-runtime suite), but the pnpm --filter <name> test invocation is uniform.
If the editor or a build reports stale types from @clerk/shared, rebuild the foundations:
pnpm turbo build --filter=@clerk/shared.
Integration-test variants (pnpm test:integration:*) and canary/snapshot releases are the long tail:
see references/setup-and-footguns.md and docs/CONTRIBUTING.md.
Each rule below restates AGENTS.md; the parenthetical is how it is enforced.
>=24.15, pnpm >=10.33. (preinstall blocks npm/yarn; engines inpackage.json.)
pnpm changeset /pnpm changeset:empty scripts are interactive prompts an agent cannot drive. A changeset is a
changelog entry for users upgrading, not a summary of the diff. See
references/changesets.md. (CI runs
pnpm changeset status --since=origin/main and fails PRs missing one.)
type(scope):, scope is mandatory. Enforced on the PR title(.github/workflows/pr-title-linter.yml), not on individual commits. There is no local
commit-msg hook. Valid scope = any packages/* short name and its clerk--stripped form
(so clerk-js accepts clerk-js or js), plus repo, release, e2e, ci, *. docs is a
valid type, not a scope. Source of truth: commitlint.config.ts.
clerk-js and ui must stay backwards-compatible across non-major releases. A new clerk-jsruntime loads into apps still pinned to an _older_ framework SDK (@clerk/nextjs, etc.), so
removing or renaming anything an older SDK calls breaks those apps in production. (break-check
flags API-surface changes in api-changes.yml, but that check is informational; shipping such a
change means a major, gated by major-version-check.yml.)
Clerk class API (packages/clerk-js/src/core/clerk.ts) require a majorversion** and !allow-major approval. (.github/workflows/major-version-check.yml.) APIs prefixed
__internal_ or exported from an /experimental subpath are exempt from SemVer guarantees.
main..changeset/<name>.md (see above, andreferences/changesets.md), then git add it. An unstaged changeset
fails CI the same as a missing one.
pnpm build, pnpm test (or the filtered forms above), pnpm lint,pnpm format:check.
the PR template and add nothing beyond its sections — in particular, never write a "Testing" /
"Test plan" / "How to test" section listing the tests added or the checks run. The Checklist
covers that and reviewers read the diff. Describe the change, not the work done on it.
Release _policy_ (when/how things ship, canary, snapshot, backports) is in docs/PUBLISH.md. This
skill stops at opening the PR.
If you are editing clerk-js or ui, answer these. Any "yes" means it is breaking, needs a
major + !allow-major, and break-check will flag it:
Clerk class public surface in core/clerk.ts?If the symbol is __internal_/__experimental_-prefixed or under /experimental, it is exempt.
Full decision matrix:
references/breaking-changes.md.
AGENTS.md: the canonical hard rules (authority for this skill).docs/CONTRIBUTING.md: full setup, testing, JSDoc/Typedoc, changeset writing.docs/PUBLISH.md: release process (stable, canary, snapshot, backport, !allow-major).docs/CICD.md: CI/CD pipeline and automated releases.docs/SECURITY.md: vulnerability reporting (do not open public issues).references/theming-architecture.md (repo root, not this skill's references/): deep dive on the@clerk/ui appearance/theming system.
setup-and-footguns.md,package-map.md,
breaking-changes.md,
changesets.md.
Analyzing or coordinating a release PR (the "Version packages" PR) is out of scope for this
skill; the release process lives in docs/PUBLISH.md and docs/CICD.md. Clerk employees may also
have dedicated analyze-javascript-release / coordinate-clerk-release skills installed globally,
but those are not shipped in this repo.
Take clerk/clerk-monorepo from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.
The instructions reference npm.
Without those the skill loads but fails at the first command.