- detect your framework — Flutter, bare React Native, or Expo (including the Expo Go evaluation lane),
- ask you the decisions that are actually yours — prebuilt chat UI vs. building screens in your own design system, where support opens from, push now or later, attachments,
- consult these docs instead of guessing — every step links the exact reference page, and the rules for AI agents are embedded,
- verify the result — it finishes by round-tripping a real message to your dashboard inbox, not by declaring success.
Your
pk_live_ key is publishable — it’s safe to paste into a prompt and
ship in your app binary. It can only register devices; it can’t read tickets.
Get it at dashboard.clariodesk.com → your app → API key.
When you create a new app, the dashboard shows this same prompt with your key
already filled in.The prompt
# Add ClarioDesk In-App Support
Integrate the ClarioDesk SDK so users can contact support and report bugs from
inside this app, and replies from the support dashboard stream back live.
Your publishable API key for this integration: `pk_live_YOUR_KEY`
## Quick setup
Before running any commands or editing any files, present the user with this
checklist:
```
Here's what I'll do to add ClarioDesk in-app support.
1. Detect your framework (Flutter, bare React Native, Expo, or native iOS/Swift)
2. Ask a few questions about how you want support to work
3. Install the SDK and initialize it with your API key
4. Add a support entry point (prebuilt chat UI, or headless in your own UI)
5. Verify it works by sending a real test message
Shall I proceed?
```
## Step 1: Detect the stack
Inspect the project root:
- `pubspec.yaml` present → **Flutter**.
- `package.json` with an `expo` dependency (or `app.json`/`app.config.*` with an
`expo` key) → **Expo**. Then determine the lane: if the project uses a dev
client / EAS builds (`expo-dev-client` dependency, `eas.json`) it gets the
full experience; if the user only runs Expo Go, everything works for
evaluation but the device key is a software fallback and remote push is
unavailable — say so, and recommend a dev build before shipping.
- `package.json` with `react-native` but no `expo` → **bare React Native**
(old vs. New Architecture doesn't matter — the SDK supports both; don't
branch on it).
- An `.xcodeproj`/`.xcworkspace` (or a `Package.swift` app target) with no
Flutter/RN markers → **native iOS (Swift)**. Requires iOS 16+; if the
deployment target is lower, say so before proceeding.
- Empty or non-mobile directory → ask which framework the user wants; offer to
scaffold (`flutter create` / `npx create-expo-app`) and continue.
## Step 2: Ask the integration decisions
Ask the user these questions before writing code. Do not assume answers you
cannot infer from the codebase; if the user has no preference, use the marked
default.
1. **Prebuilt UI or your own?** The prebuilt chat UI is themeable and ships a
complete inbox → thread → new-ticket → bug-report flow with one call
*(default)*. Alternatively, integrate headless and render support screens in
the app's own design system — more work, fully native look.
2. **Where does support open from?** A settings row, a "Help" button, a menu
item — find where the app keeps such actions and propose a spot.
3. **Push notifications for agent replies — now or later?** Later is fine and
is the default; it's additive. (Requires Firebase setup on the host app;
Expo Go can't do remote push at all.)
4. **Attachments (screenshots/photos on messages) — enabled?** Default yes for
the prebuilt UI if the app already has photo permissions, otherwise ask —
iOS requires photo-library/camera usage strings in Info.plist.
## Step 3: Install and initialize
### Flutter
```bash
flutter pub add clariodesk
```
Initialize at app start, before `runApp`:
```dart
import 'package:clariodesk/clariodesk.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
// First launch generates a hardware-backed device key and registers it.
// Later launches reuse it — no network round-trip.
await ClarioDesk.init(apiKey: 'pk_live_YOUR_KEY');
runApp(const MyApp());
}
```
Platform floors: iOS 13+, Android API 23+.
### React Native (bare and Expo)
```bash
npm install @clariodesk/react-native react-native-get-random-values
```
(Substitute the project's package manager: pnpm/yarn/bun per the lockfile.)
Secure storage peer — pick one:
```bash
npx expo install expo-secure-store # Expo
npm install react-native-keychain # bare RN
```
**Expo**: add the config plugin to app.json, then make a dev build:
```jsonc
{ "expo": { "plugins": ["@clariodesk/react-native"] } }
```
```bash
npx expo prebuild && npx expo run:ios
```
(Skip prebuild for Expo Go evaluation — the SDK transparently uses a software
key there.)
**Bare RN**: run `npx install-expo-modules@latest` once (the device-key native
module is an Expo Module), then `cd ios && pod install`.
Initialize — and note the RNG import **must be the first import in the app
entry file** (index.js), before anything else:
```ts
// index.js — very first line:
import 'react-native-get-random-values';
import { ClarioDesk } from '@clariodesk/react-native';
await ClarioDesk.init({ apiKey: 'pk_live_YOUR_KEY' });
```
### Native iOS (Swift)
Add the package via Swift Package Manager — in Xcode, File → Add Package
Dependencies… with the URL, or in Package.swift:
```swift
.package(url: "https://github.com/clariodesk/clariodesk-swift", from: "0.1.1")
```
Link the products the app needs: `ClarioDesk` (headless core) and — for the
prebuilt UI lane — `ClarioDeskUI`. A headless host links only `ClarioDesk`;
Swift dead-strips the UI. Requires iOS 16+.
Initialize at app start (fire-and-forget, no await — AppDelegate or the
`App` initializer):
```swift
import ClarioDesk
ClarioDesk.initialize(.init(apiKey: "pk_live_YOUR_KEY"))
```
The device key is CryptoKit/Secure Enclave-backed (software fallback on the
simulator). Note: an **unsigned** host can't write the Keychain
(`errSecMissingEntitlement -34018`) — real signed apps are unaffected.
### Wire identity (all platforms)
First check whether Dashboard → Verified identity is enabled for this app.
Without it, `identify()` is label-only metadata and should be called in two
places; with it, use the configured token provider and the ordered lifecycle in
`references/identity-and-keys.md` instead.
1. **On every app launch**, hydrated from the app's persisted session. This is
the step integrations most often miss: existing logged-in users never pass
through the login screen again, so a login-only hook leaves them unlabeled.
2. **Right after a fresh login/signup.**
```dart
// Flutter
await ClarioDesk.identify(externalId: user.id, email: user.email, traits: {'plan': user.plan});
```
```ts
// React Native
await ClarioDesk.identify({ externalId: user.id, email: user.email });
```
```swift
// Swift
try await ClarioDesk.identify(externalId: user.id, email: user.email)
```
In label-only mode, acknowledged `reset()` → `init()` can isolate a shared
device. In Verified identity mode, logout/account switch must await
`clearIdentity()` before changing the host user; `reset()` is reserved for
removing this installation.
If the app has no auth, skip `identify()` entirely — anonymous tickets work;
the dashboard shows the device with an "Unverified device" badge.
## Step 4: Add the support UI
### Prebuilt UI lane (default)
**Flutter** — pass a theme at init so the modal matches the app, then open it
from the entry point chosen in Step 2:
```dart
await ClarioDesk.init(
apiKey: 'pk_live_YOUR_KEY',
theme: ClarioDeskTheme(
primaryColor: /* app accent */,
backgroundColor: /* app background */,
surfaceColor: /* cards/bubbles */,
textColor: /* primary text */,
mutedTextColor: /* secondary text */,
appBar: ClarioDeskAppBarTheme(title: 'Support'),
),
);
// From the entry point:
ClarioDesk.openInbox(context);
```
Pull the actual colors from the app's existing theme/design tokens — do not
invent a palette. The theme surface is deliberately small (colors + app bar
only); if the user wants more control than that, they want the headless lane.
**React Native** — wrap the app once, open from anywhere:
```tsx
import { ClarioDeskProvider, openInbox } from '@clariodesk/react-native/ui';
<ClarioDeskProvider theme={{ primary: brand.accent, cornerRadius: 18, mode: 'system' }}>
<App />
</ClarioDeskProvider>;
// From the entry point:
openInbox(); // also: openTicket(id), openNewConversation(), openBugReport()
```
**Swift** — one call from SwiftUI or UIKit; the modal presents on the
top-most view controller:
```swift
import ClarioDeskUI
// From the entry point:
ClarioDeskWidgets.openInbox(theme: ClarioDeskTheme(primary: /* app accent */))
// also: openBugReport()
```
The theme is 13 optional tokens — unset ones derive light/dark from the
system; pull any you do set from the app's existing design tokens.
The prebuilt UI presents in a self-owned modal — it never touches the app's
navigation (GoRouter/Navigator 2.0/react-navigation/SwiftUI NavigationStack
all unaffected).
If attachments were enabled in Step 2 (React Native): install the picker peers
(`npx expo install expo-image-picker expo-document-picker expo-image-manipulator`
for Expo; `npm install react-native-image-picker @react-native-documents/picker`
for bare RN), pass a `picker` to `ClarioDeskProvider`, and add the iOS usage
strings (`NSPhotoLibraryUsageDescription`, plus camera/microphone if camera
capture is on) to Info.plist.
### Headless lane (custom UI in the app's design system)
Build the support screens with the app's own components on top of the SDK's
methods and live subscriptions. Follow the API exactly as documented — do not
guess method names:
- Flutter: https://docs.clariodesk.com/flutter/api-reference
(`createTicket`, `sendMessage`, `ticketsStream()`, `messagesStream(id)`, …)
- React Native: https://docs.clariodesk.com/react-native/api-reference — use
the hooks (`useTickets`, `useMessages`, `useConnection`, …) from
`@clariodesk/react-native/hooks`.
- Swift: https://docs.clariodesk.com/swift/api-reference — replay-last
`AsyncStream` reads (`for try await tickets in ClarioDesk.tickets`) from
SwiftUI, or the closure variants (`subscribeTickets { … }`) from UIKit.
Match the app's existing screens: reuse its list items, buttons, spacing, and
color tokens so the support flow looks native to the app. Render optimistic
state: a message with `pending: true` shows "sending…", `failed: true` gets
tap-to-retry via `retryMessage`.
## Step 5: Push notifications (only if chosen in Step 2)
**React Native** — push is a deliberately separate package (Firebase's native
code must not autolink into apps that didn't opt in):
```bash
npm install @clariodesk/react-native-push @react-native-firebase/app @react-native-firebase/messaging
```
```ts
import { FirebaseTokenProvider } from '@clariodesk/react-native-push';
await ClarioDesk.init({ apiKey: 'pk_live_YOUR_KEY', pushTokenProvider: new FirebaseTokenProvider() });
```
Register the background handler in index.js at startup (the #1 push
setup-failure cause), and route notification taps with
`ClarioDesk.openTicketFromPush(data)`. Full guide:
https://docs.clariodesk.com/react-native/push
**Flutter** — the SDK takes an FCM token through a `PushTokenProvider` seam
(it never imports firebase_messaging itself). Follow
https://docs.clariodesk.com/concepts/push-notifications for the wiring.
**Swift** — APNs-direct, **no Firebase**. Forward the raw APNs token from the
AppDelegate — that's the whole wiring:
```swift
func application(_ app: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken token: Data) {
ClarioDesk.setAPNSDeviceToken(token)
}
```
Full guide: https://docs.clariodesk.com/swift/push
Every platform also needs the app's push credentials uploaded once in the
ClarioDesk dashboard (app settings → push): FCM service account for
Flutter/React Native, an APNs `.p8` key for Swift.
## Step 6: Verify
Run the app (`flutter run` / `npx expo run:ios` / `npx react-native run-ios`
/ Xcode ⌘R). Then, as the user would:
1. Open the support entry point and send a message ("test from ClarioDesk
setup").
2. Confirm the message appears in the dashboard inbox at
https://dashboard.clariodesk.com — if the app-setup page is open, its
"Watching for devices" check flips as soon as the app registered.
3. Reply from the dashboard and confirm the reply streams into the app live
(no restart).
If registration or realtime fails, check the troubleshooting guides:
https://docs.clariodesk.com/integrate-flutter /
https://docs.clariodesk.com/integrate-react-native /
https://docs.clariodesk.com/integrate-swift
## When unsure, use the docs
Never guess an API. Every page below is also available as plain markdown for
you to fetch, and https://docs.clariodesk.com/llms.txt indexes everything.
| Topic | URL |
|---|---|
| Quickstart (all platforms) | https://docs.clariodesk.com/quickstart |
| Flutter integration walkthrough | https://docs.clariodesk.com/integrate-flutter |
| Flutter install / lifecycle / prebuilt UI / API | https://docs.clariodesk.com/flutter/installation · /flutter/lifecycle · /flutter/prebuilt-ui · /flutter/api-reference |
| React Native integration walkthrough | https://docs.clariodesk.com/integrate-react-native |
| RN install / lifecycle / prebuilt UI / push / API | https://docs.clariodesk.com/react-native/installation · /react-native/lifecycle · /react-native/prebuilt-ui · /react-native/push · /react-native/api-reference |
| Swift integration walkthrough | https://docs.clariodesk.com/integrate-swift |
| Swift install / lifecycle / prebuilt UI / push / API | https://docs.clariodesk.com/swift/installation · /swift/lifecycle · /swift/prebuilt-ui · /swift/push · /swift/api-reference |
| How auth works (device-is-identity) | https://docs.clariodesk.com/concepts/authentication |
| Identity lifecycle (launch/login/logout/switch) | https://docs.clariodesk.com/concepts/identity-lifecycle |
| Attachments / realtime / CSAT | https://docs.clariodesk.com/concepts/attachments · /concepts/realtime · /concepts/csat |
| Rules for AI agents | https://docs.clariodesk.com/concepts/agent-rules |
## Critical rules
- `pk_live_YOUR_KEY` is a **publishable** key — safe to ship in the app
binary. It can only register new devices; it cannot read tickets or
impersonate users. There is no secret key and no `appId` — the key encodes
the app.
- The SDK's device key always authenticates requests. Do not invent additional
auth in label-only mode. If Verified identity is enabled, use exactly its
configured host-token/OIDC profile and never ship the signing secret.
- Label-only mode identifies on every launch. Verified mode uses a fresh proof
on session restore/login and `clearIdentity()` before logout/switch;
`reset()` deprovisions only this installation.
- Don't mix modes: either the prebuilt UI owns the support screens, or the
app's custom screens do — not both for the same flow.
- React Native: `import 'react-native-get-random-values'` must be the **first
import** in the entry file.
- React Native push lives in `@clariodesk/react-native-push` — never add
Firebase packages to an app that didn't opt into push.
- Native iOS (Swift) push is APNs-direct — never add Firebase to a Swift
host; the raw APNs token is all the SDK needs.
- Expo Go is for evaluation only (software device key, no remote push) — ship
with a dev build.
- Do not read or print the contents of the user's `.env` or credential files;
the only credential this integration needs is the publishable key above.
## After setup
Tell the user to send themselves a first support message from the app, then
reply to it from the dashboard inbox (https://dashboard.clariodesk.com) and
watch it arrive in-app live. Suggest exploring next: push notifications for agent
replies, attachments, and CSAT ratings — each is an additive follow-up
(https://docs.clariodesk.com).
Connect the docs MCP server
These docs also run a hosted MCP server athttps://docs.clariodesk.com/mcp
(tools: search_clario_desk for search, query_docs_filesystem_clario_desk
for reading pages). With it connected, your agent retrieves live ClarioDesk
docs mid-task instead of guessing.
claude mcp add --transport http clariodesk-docs https://docs.clariodesk.com/mcp
{
"mcpServers": {
"clariodesk-docs": { "url": "https://docs.clariodesk.com/mcp" }
}
}
{
"servers": {
"clariodesk-docs": { "type": "http", "url": "https://docs.clariodesk.com/mcp" }
}
}
Working docs-first instead?
If you’d rather have your agent research as it goes, point it at the machine-readable docs:llms.txt— index of every page;llms-full.txt— the full docs in one file.- The distilled rules for AI agents.
- Every page here can be pulled as markdown by appending
.mdto its URL, or through the docs MCP server above.