> ## Documentation Index
> Fetch the complete documentation index at: https://docs.clariodesk.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Rules for AI agents

> Critical rules for integrating the ClarioDesk SDK with an AI coding agent — key handling, identity, package boundaries, and the mistakes to avoid.

If you are an AI coding agent integrating ClarioDesk into an app, these rules
override anything you might assume from other SDKs. They exist because each one
is a mistake agents actually make.

<Note>
  For a complete guided integration, use the [install prompt](/claude-code) — it
  walks the whole flow including the questions to ask the developer. This page is
  the distilled rule set to keep in context while you work.
</Note>

## The rules

1. **The `pk_live_…` key is publishable — safe to ship in the app binary.** It
   only authorizes a fresh install to register a device; it cannot read tickets
   or impersonate users. There is no secret key to hide, no `appId` parameter,
   and no server-side environment variable — the key encodes the app. Do not
   move it to a backend, do not build a key-proxy endpoint.

2. **Never build auth for ClarioDesk.** There are no JWTs, no refresh tokens,
   no session endpoints. The SDK generates a non-extractable hardware-backed
   device key on first launch and signs every request with it
   (device-is-identity — see [Authentication](/concepts/authentication)).
   `identify({ externalId, email, traits })` is **metadata only** and grants no
   access.

3. **Call `identify()` on every app launch for logged-in users**, hydrated from
   the app's persisted session — not only in the login flow. Users who were
   already signed in before the SDK was added never pass through login again;
   a login-only hook leaves them unlabeled. `identify()` is idempotent, so
   repeated calls are correct, not wasteful. See
   [Identity lifecycle](/concepts/identity-lifecycle).

4. **`reset()` on logout; never rebind a device.** Account switch =
   `reset()` → `init()` → `identify()`. Each device row carries an independent
   ticket history — rebinding one device across users is always wrong.

5. **Two modes, one install — don't mix them.** Either the prebuilt UI
   (Flutter: `ClarioDesk.openInbox(context)`; React Native:
   `@clariodesk/react-native/ui`) owns the support screens, or the app's custom
   screens built on the headless API do. Don't hand-roll one screen inside the
   prebuilt flow.

6. **React Native: `import 'react-native-get-random-values'` must be the first
   import in the entry file** — before any other import, or key generation
   fails at runtime.

7. **Push is a separate package on purpose.** React Native push lives in
   `@clariodesk/react-native-push` because Firebase's native code autolinks
   into every host that installs it — never add it (or any
   `@react-native-firebase/*` package) to an app that didn't opt into push.
   Flutter receives FCM tokens through the `PushTokenProvider` seam; the SDK
   never imports `firebase_messaging`.

8. **Expo Go is an evaluation lane, not a shipping lane.** The SDK
   transparently falls back to a software P-256 key there (no native modules)
   and remote push is unavailable. Everything else works. Recommend a dev
   build (`npx expo prebuild && npx expo run:ios`) before release.

9. **Attachments need iOS usage strings.** Enabling the picker means the host
   app must declare `NSPhotoLibraryUsageDescription` (plus camera/microphone
   variants if capture is enabled) in Info.plist.

10. **Never guess an API name.** The full surface is small and documented —
    Flutter: [API reference](/flutter/api-reference); React Native:
    [API reference](/react-native/api-reference). Machine-readable index:
    [`llms.txt`](https://docs.clariodesk.com/llms.txt) /
    [`llms-full.txt`](https://docs.clariodesk.com/llms-full.txt); any page is
    fetchable as markdown by appending `.md` to its URL. If the ClarioDesk
    docs MCP server is connected (`https://docs.clariodesk.com/mcp` — see
    [Install with AI](/claude-code)), prefer its `search_clario_desk` tool
    over web fetches.

## Quick facts

| Fact           | Flutter                                          | React Native                                                                                      |
| -------------- | ------------------------------------------------ | ------------------------------------------------------------------------------------------------- |
| Package        | `clariodesk` (pub.dev)                           | `@clariodesk/react-native` (+ `/ui`, `/hooks` subpaths; `@clariodesk/react-native-push` separate) |
| Install        | `flutter pub add clariodesk`                     | `npm install @clariodesk/react-native react-native-get-random-values` + secure-storage peer       |
| Init           | `await ClarioDesk.init(apiKey: 'pk_live_…')`     | `await ClarioDesk.init({ apiKey: 'pk_live_…' })`                                                  |
| Prebuilt UI    | theme at `init`, `ClarioDesk.openInbox(context)` | `<ClarioDeskProvider theme={…}>` + `openInbox()`                                                  |
| Reactive reads | `ticketsStream()` / `messagesStream(id)`         | `subscribe*` fns or hooks from `…/hooks`                                                          |
| Platform floor | iOS 13+, Android API 23+                         | bare RN (old + New Arch), Expo dev build, Expo Go (degraded)                                      |

## Integration flow

Detect the stack → ask the developer the four decisions (prebuilt vs. custom
UI, entry point, push, attachments) → install → `init` + `identify` wiring →
UI → **verify by round-tripping a real message** to the dashboard inbox. The
[install prompt](/claude-code) encodes this flow end to end.
