All skills
clerk avatar

/clerk-orgs

@47c55cd official
by clerkclerk/skills83 stars
5

Clerk Organizations for B2B and multi-tenant apps - org switching, roles and permissions, verified domains, and enterprise SSO. Use for team workspaces, RBAC, org-scoped routing, member management. Also load this when a project treats teams, workspaces, tenants, or companies as its customers - shared accounts, inviting teammates, per-seat pricing, per-company data isolation - even when the words "organization" or "B2B" are never used.

Use this Skill: https://skilld.dev/gh/clerk/skills/clerk-orgs

This session only. Nothing lands on disk.

referencesroles-permissions.md

≈1.4k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Roles and Permissions

Clerk Organizations use Role-Based Access Control (RBAC). Every member has one Role per org; Roles carry Permissions (a mix of Clerk-provided System Permissions and your own custom Permissions).

Default Roles

Role Default meaning
org:admin Full access — holds all System Permissions, can manage the Organization and its memberships
org:member Read-only members. By default has only org:sys_memberships:read and org:sys_billing:read

Both slugs are automatically created when Organizations are enabled. You cannot delete a default Role if it's set as the org's Creator or Default Role — reassign to another Role first.

System Permissions (canonical catalog)

These are the only built-in Permissions. Use them verbatim; do NOT invent shorter forms like org:manage_members or org:create.

Slug Purpose
org:sys_profile:manage Edit Organization profile (name, slug, logo)
org:sys_profile:delete Delete the Organization
org:sys_memberships:read View the member list
org:sys_memberships:manage Invite, remove, and change roles of members
org:sys_domains:read View Verified Domains
org:sys_domains:manage Add / verify / remove Verified Domains
org:sys_billing:read View billing info (subscription, invoices)
org:sys_billing:manage Manage billing (change plan, payment method)

Creator Role requirement. The Role that Clerk assigns to a user who creates a new Organization MUST carry at minimum:

  • org:sys_memberships:manage
  • org:sys_memberships:read
  • org:sys_profile:delete

If you reassign the Creator Role, ensure the replacement Role has these three at minimum.

Custom Roles

Up to 10 custom Roles per instance. Create via Dashboard → Roles & Permissions → Add role, or via clerk api -X POST /v1/organization_roles with body {"name":"Billing Manager","key":"org:billing","description":"..."}. The key follows org:<role> format. Examples:

  • org:billing — carries org:sys_billing:manage
  • org:reports_viewer — carries your custom org:reports:view

Custom Permissions

Naming convention: org:<resource>:<action>. Examples: org:reports:view, org:api_keys:create, org:posts:edit.

Create via Dashboard → Roles & Permissions → Permissions tab → Add permission, or via two steps: (1) clerk api -X POST /v1/organization_permissions with body {"name":"Edit Posts","key":"org:posts:edit","description":"..."} to create the permission, then (2) clerk api -X POST /v1/organization_roles/{role_id}/permissions/{permission_id} to attach it to a role. Permissions are attached to Roles inside a Role Set.

Role Sets

Roles are surfaced to Organizations through Role Sets — this controls which Roles can be assigned within a given Organization. Each Organization is assigned exactly one Role Set.

Default behavior: all orgs share the default Role Set. If you need per-org role variations (e.g. one customer org has its own org:support role), create a second Role Set and assign it.

Billing Gates Permissions

When Clerk Billing is enabled, a custom Permission org:<feature>:<action> only returns true from has() if the <feature> part matches a Feature included in the organization's active Plan.

Example: user has role org:admin with Permission org:posts:edit. has({ permission: 'org:posts:edit' }) returns:

  • false — if the active Plan does not include the posts Feature
  • true — if the active Plan includes the posts Feature

This applies regardless of role assignment. See clerk-billing skill for the full feature-vs-plan model.

Change a User's Role

Via Backend API:

import { clerkClient } from '@clerk/nextjs/server'

const clerk = await clerkClient()
await clerk.organizations.updateOrganizationMembership({
  organizationId: 'org_123',
  userId: 'user_123',
  role: 'org:admin',
})

Via Dashboard: Users → select member → change role dropdown.

Via UI: the <OrganizationProfile /> component's Members tab includes a role-change dropdown for admins.

Checking Roles and Permissions

Three surfaces, same semantics:

// Server (Next.js)
import { auth } from '@clerk/nextjs/server'
const { has } = await auth()
has({ role: 'org:admin' })
has({ permission: 'org:sys_memberships:manage' })
// Client (any React-based SDK)
import { useAuth } from '@clerk/nextjs'
const { has, isLoaded } = useAuth()
if (!isLoaded) return null
has?.({ role: 'org:admin' })
// JSX conditional
import { Show } from '@clerk/nextjs'
<Show when={{ role: 'org:admin' }}>
  <AdminPanel />
</Show>

Key Rules

  • Never invent permission slugs. If you don't see it in the System Permissions catalog above or you haven't created it as a custom Permission (Dashboard or BAPI), it doesn't exist.
  • org: prefix is mandatory for all org-scoped permissions.
  • Always check isLoaded before trusting has on the client. On first render has can be undefined — use optional chaining (has?.()) or guard on isLoaded.
  • Case-sensitive. org:Admin is not org:admin.
  • Role changes require session refresh. If you change a user's role and has() still returns the old value, the session token is stale. await clerk.session?.reload() on the client, or navigate to force a new session.

Source: SKILL.md on GitHub

No alerts6d5 checks · Risk SAFE
  • Gen Agent Trust Hub6d

    The skill provides legitimate guidance and tools for integrating Clerk Organizations into applications. It includes safety instructions requiring user confirmation for administrative actions and uses official vendor resources.

  • Socket6d

    No alerts

  • Snyk6d

    Risk: LOW · No issues

  • Runlayer7mo

    2 files scanned · No issues

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at 47c55cd. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub yesterday.

Activeupdated last week
What it can do
Network
metadata
{
  "author": "clerk",
  "version": "3.1.1"
}
All 1 allowed tools
WebFetch
Other metadata
compatibility
Requires NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY and CLERK_SECRET_KEY. Organizations must be enabled in Clerk Dashboard → Organizations. Membership mode (required vs optional) must match the B2B vs B2C + B2B coexistence story of your app.
  • Next.js
  • clerk
  • b2b
  • saas
  • organizations
  • rbac
  • multi-tenant
  • sso
  • authentication

README badge

README badge for clerk/skills/clerk-orgs

Manages multi-tenant B2B SaaS with Clerk Organizations — handles org creation, member invitations, role-based access control, verified domains, and enterprise SSO. Requires Organizations enabled in Clerk Dashboard and targets Next.js, React, and other Clerk SDK frameworks for team workspaces and org-scoped routing.

Generated from the current SKILL.md.

Does this work with frameworks other than Next.js?
Yes. The skill covers @clerk/nextjs by default, but the same feature-level APIs (has(), orgId, <OrganizationSwitcher />, <Show>) work across @clerk/react, @clerk/astro, @clerk/vue, @clerk/expo, @clerk/react-router, and @clerk/tanstack-react-start. Framework-specific patterns like middleware live in the nextjs-patterns reference.
What's the difference between Membership required and Membership optional?
Membership required (default) disables personal accounts and routes signed-in users through a choose-organization task, suitable for B2B-only apps. Membership optional keeps personal accounts available alongside org memberships, needed for B2C + B2B coexistence or apps with personal subscriptions.
How do I check if a user has a specific permission?
Use the has() function with a permission slug: has({ permission: 'org:sys_memberships:manage' }). System permissions prefix with org:sys_; custom permissions use org:<resource>:<action>. The full catalog is in references/roles-permissions.md.
Can I manage organizations and invitations programmatically?
Yes. The skill includes Backend API commands (clerk api) for org CRUD, membership management, and invitations. You can also use clerkClient().organizations.* in code. Billing/seat limits are handled by the clerk-billing skill.

Generated from the current SKILL.md. These answers refresh after source changes.