This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
The Clerk Android SDK is a modular authentication SDK for Android applications. It provides two main artifacts:
clerk-android-api(source/api) - Core API and authentication logicclerk-android-ui(source/ui) - Prebuilt Jetpack Compose UI components (includes API)
The SDK enables user management with sign-up, sign-in, MFA, passkeys, OAuth/SSO, and profile management.
# Build the entire project
./gradlew build
# Build specific modules
./gradlew :source:api:build
./gradlew :source:ui:build
# Assemble without tests
./gradlew assemble
# Verify Maven publishing metadata locally
./gradlew :source:api:publishToMavenLocal# Run all tests
./gradlew test
# Run tests for specific module
./gradlew :source:api:test
./gradlew :source:ui:test
# Run a single test class
./gradlew :source:api:test --tests "com.clerk.sdk.SpecificTest"
# Run UI snapshot tests (Paparazzi)
./gradlew :source:ui:testDebug
./gradlew :source:ui:recordPaparazziDebug # Update snapshots
# Run Android instrumentation tests
./gradlew connectedAndroidTest
./gradlew :source:api:connectedDebugAndroidTest# Format code (must pass before commit)
./gradlew spotlessApply
# Check code formatting
./gradlew spotlessCheck
# Run detekt static analysis (config: config/detekt/detekt.yml)
./gradlew detekt
# Run Android lint
./gradlew lint
./gradlew :source:api:lintDebug# Generate Dokka API documentation (outputs to docs/)
./gradlew dokkaGenerate
./gradlew dokkaGenerateHtml# Build and install sample apps
./gradlew :samples:quickstart:installDebug
./gradlew :samples:custom-flows:installDebug
./gradlew :samples:linear-clone:installDebug
./gradlew :samples:prebuilt-ui:installDebugNote: Before running samples, update Clerk publishable keys in gradle.properties:
QUICKSTART_CLERK_PUBLISHABLE_KEYCUSTOM_FLOWS_CLERK_PUBLISHABLE_KEYLINEAR_CLONE_CLERK_PUBLISHABLE_KEYPREBUILT_UI_CLERK_PUBLISHABLE_KEY
# Publish to Maven Central
./gradlew :source:api:publishToMavenCentral
./gradlew :source:ui:publishToMavenCentralclerk-android/
├── source/
│ ├── api/ # Core authentication logic (clerk-android-api)
│ ├── ui/ # Jetpack Compose UI components (clerk-android-ui)
│ └── telemetry/ # Kotlin Multiplatform telemetry
├── samples/ # Example implementations
│ ├── quickstart/ # Basic integration
│ ├── custom-flows/ # Advanced custom auth flows
│ ├── linear-clone/ # OAuth/Passkey/Email flows with Compose navigation
│ └── prebuilt-ui/ # Prebuilt UI component examples
├── config/ # Repo-wide lint and static-analysis settings
└── workbench/ # Internal development tools
Core Architecture:
- Retrofit 2 for HTTP with OkHttp middleware pipeline
- Kotlinx Serialization with snake_case naming
- Result-based error handling via
ClerkResult<T, E>sealed interface (no exceptions) - Reactive state management with Kotlin StateFlows
Key Components:
-
Clerk(singleton object) - Main SDK entry point atcom.clerk.api.Clerk- Initialize:
Clerk.initialize(publishableKey, context) - Reactive state:
Clerk.sessionFlow,Clerk.userFlow,Clerk.isInitialized - Lazy initialization with error recovery
- Initialize:
-
Authentication Flow Classes:
SignIn- Sign-in state machine with factor verificationSignUp- Sign-up state machine with field collectionSession- Active session management with JWT token handlingUser- User profile and account management
-
Network Layer:
ClerkApi- Retrofit service configurationnetwork/api/*- Service interfaces (ClientApi, SignInApi, SignUpApi, SessionApi, UserApi, etc.)network/middleware/*- Request/response interceptors (versioning, client syncing, device attestation)network/model/*- Serializable data models (Client, User, Session, Factor, Verification, etc.)
-
Authentication Features:
passkeys/- WebAuthn/Passkey via Google Credential Managersso/- OAuth/SSO providers (Google One Tap, enterprise SSO)organizations/- Multi-tenant organization supportsession/- JWT token caching and refresh
Result Handling Pattern:
when (val result = signIn.attemptFirstFactor(...)) {
is ClerkResult.Success -> // Handle success
is ClerkResult.Failure -> // Handle error
}Core Architecture:
- Jetpack Compose with Material Design 3
- MVVM pattern with ViewModels per screen
- CompositionLocal for dependency injection (
LocalAuthState,LocalTelemetryCollector) - Custom navigation using NavBackStack (androidx.navigation3)
- Paparazzi for snapshot testing
Key Components:
-
Authentication Screens:
AuthView- Main navigation container with slide animationsAuthStartView- Initial identifier entry (email/username/phone)signin/*- Sign-in factor screens (password, email code, phone code, passkey, OTP, backup code)signup/*- Sign-up flow (collect fields, verify email/phone, complete profile)
-
User Management Screens:
userprofile/*- Profile management (account, email, phone, security, MFA)userbutton/*- User menu dropdown component
-
Reusable Components:
core/- Input fields, buttons, avatars, navigation componentstheme/- Material Design theming with dynamic color support
-
State Management:
AuthState- Local UI state (form inputs, navigation, back stack)AuthStartViewModel- Main authentication orchestration- ViewModels map API
ClerkResultto UI states (Idle, Loading, Error, Success)
Sign-In Flow:
AuthStartView → SignIn.create(identifier)
→ First Factor (password/code/passkey)
→ Optional Second Factor (MFA)
→ Session Created
Sign-Up Flow:
AuthStartView → SignUp.create(fields)
→ Collect Required Fields
→ Verify Email/Phone
→ Complete Profile
→ Session Created
Key Patterns:
- Multi-factor authentication - First factor required, second factor optional based on configuration
- Extensible verification - Supports password, email_code, phone_code, passkey, totp, backup_code
- OAuth/SSO - Web-based flows via RedirectConfiguration, native Google One Tap
- Error recovery - SignUp fallback when SignIn fails with "identifier_not_found"
Outgoing (Request):
VersioningUserAgentMiddleware- Adds SDK version to User-AgentUrlAppendingMiddleware- Appends proxy URL if configuredDeviceAssertionMiddleware- Adds device attestation headers
Incoming (Response):
ClientSyncingMiddleware- Extracts and syncs client state from API responsesDeviceTokenSavingMiddleware- Persists device attestation tokens
Unit Tests (JVM with Robolectric):
source/api/src/test/- Network serialization, passkeys, SSO, storage, configurationsource/ui/src/test/- ViewModels, theme, components, navigation
UI Snapshot Tests (Paparazzi):
source/ui/src/test/- Visual regression testing of Compose components- Update snapshots:
./gradlew :source:ui:recordPaparazziDebug
Instrumentation Tests:
source/*/src/androidTest/- Android-specific integration tests
Coverage & Regression:
- Target >=80% coverage on touched packages
- Add regression tests whenever altering auth flows, attestation, or persistence logic
- Kotlin code style: Official Kotlin style guide
- Formatting: ktfmt Google Style (enforced via Spotless)
- Linting: Detekt with all rules enabled — avoid wildcard imports, prefer explicit visibility
- Naming: Package names mirror feature scopes (e.g.,
com.clerk.api.sso,com.clerk.ui.signup). Class names should describe intent (SessionTokenFetcher,AuthStartViewModel). - Must pass
./gradlew spotlessCheck detektbefore committing
- Follow Conventional Commits style (
chore(deps): …,fix: …). Scope optional but encouraged (feature(scope): summary). Write bodies describing rationale and mention affected modules. - Pull requests should state the problem, link GitHub issues, and attach emulator screenshots or Paparazzi diffs for UI tweaks. Mention migrations or new Gradle knobs explicitly.
- Before requesting review, run
spotlessCheck,detekt,lint, relevanttesttasks, and at least one sample install so reviewers can focus on logic instead of build failures.
- Define data models in
source/api/src/main/kotlin/com/clerk/api/network/model/ - Add Retrofit service interface in
source/api/src/main/kotlin/com/clerk/api/network/api/ - Add serialization tests in
source/api/src/test/.../network/ - Expose through
Clerkobject or extension functions on domain models
- Create Composable in appropriate package (
signin/,signup/,core/, etc.) - Add ViewModel if stateful, inheriting from
androidx.lifecycle.ViewModel - Use
LocalAuthStatefor accessing authentication state - Add Paparazzi snapshot tests in
source/ui/src/test/ - Update snapshots with
./gradlew :source:ui:recordPaparazziDebug
Always use pattern matching instead of exceptions:
when (val result = apiCall()) {
is ClerkResult.Success -> result.data // Access successful result
is ClerkResult.Failure -> result.error // Handle error
}- Singleton -
Clerk,ClerkApifor global SDK state - Sealed Classes -
ClerkResult<T, E>for type-safe error handling - Extension Functions -
SignIn.create(),SignUp.create()for idiomatic Kotlin - StateFlow - Reactive session, user state throughout SDK
- CompositionLocal - Dependency injection in Compose tree
- Middleware/Interceptor - OkHttp interceptors for cross-cutting concerns
- Result Type - No checked exceptions, explicit error handling
API Module:
- Retrofit 2 + OkHttp (HTTP)
- Kotlinx Serialization (JSON with snake_case)
- Google Play Services (OAuth, Credentials, Play Integrity)
- Android Credentials Manager (Passkeys)
- JWT Decode
UI Module:
- Jetpack Compose + Material 3
- Androidx Navigation 3
- Coil (image loading)
- libphonenumber (phone validation)
- MaterialKolor (dynamic theming)
- Paparazzi (UI testing)