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

# Getting Started

> Clone, run in the webview, and get a chat answering on a simulator.

The shortest path from clone to a running chat.

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
git clone https://github.com/MervinPraison/PraisonAI
cd PraisonAI/src/praisonai-mobile
npm install && npm run check
```

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph LR
    Clone[📦 Clone] --> Install[⚙️ npm install]
    Install --> Check[✅ npm run check]
    Check --> Build[🪟 npm run build]
    Build --> Device[📱 Simulator]

    classDef step fill:#189AB4,stroke:#7C90A0,color:#fff
    classDef start fill:#8B0000,stroke:#7C90A0,color:#fff
    classDef done fill:#10B981,stroke:#7C90A0,color:#fff

    class Clone start
    class Install,Check,Build step
    class Device done
```

## Quick Start

<Steps>
  <Step title="Install">
    ```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    cd PraisonAI/src/praisonai-mobile
    npm install
    ```

    The package is private and needs Node `>=22.18`. Runtime dependencies load through adapters, so there is no runtime `dependencies` block.
  </Step>

  <Step title="Run the gates">
    ```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    npm run typecheck
    npm run test
    npm run check
    ```

    `check` chains `typecheck`, `boundaries`, and `test`.
  </Step>

  <Step title="Build the webview bundle">
    ```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    npm run build
    ```
  </Step>
</Steps>

***

## Package Scripts

Every script the package ships, from `package.json`.

| Script           | What it does                                      |
| ---------------- | ------------------------------------------------- |
| `typecheck`      | `tsc -p tsconfig.json`.                           |
| `test`           | Runs the `node --test` suite across every layer.  |
| `boundaries`     | Fails the build if an import crosses a seam.      |
| `build`          | Builds the webview bundle.                        |
| `test:bundle`    | Runs the bundle-gate's own suite.                 |
| `check`          | `typecheck` + `boundaries` + `test`.              |
| `check:upstream` | Checks the real `Agent` still satisfies the port. |
| `build:webview`  | Same as `build`.                                  |

***

## Platform projects are already committed

The repo ships committed iOS and Android platform projects at `src-tauri/gen/apple` and `src-tauri/gen/android`, so nothing extra is needed to *build* the mobile apps — CI proves both build on every PR touching `src/praisonai-mobile/**`. See [Platform Builds](/docs/features/mobile/platform-builds) for the workflow and the local build commands.

***

## Swap the Engine

Which engine answers is a setting, read at boot in `app/src/main.ts`. Change one value.

```ts theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
import { appEngines, defaultEngineIdFor } from "praisonai-mobile/app/main";

const booted = await createApp({
  storage: platform.storage,
  secrets: platform.secrets,
  time: platform.time,
  shell: platform.shell,
  engines: (persistence, settings, onIgnored) =>
    appEngines({ settings, http: platform.http, persistence, onIgnored }),
  settingDefs: SETTING_DEFS,
  // The first-launch default when no engineId is persisted. Chosen by
  // platform kind: `praisonai-ts` on tauri (a device), `remote-http` on
  // web (see Engines). A persisted engineId always wins over this.
  engineId: defaultEngineIdFor(platform.kind),
  onPublish: publish,
  now: () => Date.now(),
  newChatId: () => globalThis.crypto.randomUUID(),
});
```

`engineId` is no longer a literal — `defaultEngineIdFor(platform.kind)` picks it by platform kind: `"tauri"` (a device, including desktop Tauri) defaults to the in-process `praisonai-ts`, `"web"` to `remote-http` (see [Engines → First-Launch Default](/docs/features/mobile/engines#first-launch-default) for why). A persisted `engineId` still wins over this default.

<Note>
  `mount(deps)` also takes an optional `locales?: readonly string[]` alongside `now` and `newChatId`. Injecting it makes locale-dependent layout deterministic in a test; when omitted it defaults to the host's `navigator.languages`. See [i18n & A11y → `MountDeps.locales`](/docs/features/mobile/i18n-and-a11y#mountdeps-locales-injectable-deterministic).

  ```ts theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
  import { mount } from "praisonai-mobile/app/main";

  await mount({
    root,
    now: () => Date.now(),
    newChatId: () => globalThis.crypto.randomUUID(),
    locales: ["ar", "en"], // optional; defaults to navigator.languages
  });
  ```
</Note>

The in-process engine's factory is supplied by `appEngines`, so `praisonai-ts` is on offer in real builds, and the picker (`SETTING_DEFS.engineId.choices`) now lists **both** `remote-http` and `praisonai-ts`. The shipping build can construct the in-process engine because its module ships as a lazy chunk fetched through `import("praisonai/mobile")` — so offering it in the picker is offering a choice the build can honour, not a brick.

<Note>
  The app runs on a device today with the in-process engine: it boots into `praisonai-ts` and reaches a first turn. The remaining gap is not the module — that ships — but the **API-key setting**, which the registry does not yet declare, so a real first turn fails **recoverably** at the model layer (a named `error` row, not a crash). A key setting is a tracked follow-up. See [Engines → The known API-key gap](/docs/features/mobile/engines#the-known-api-key-gap).
</Note>

***

## First launch

The first screen tells a new user what the app is and that it needs a key — before any message is sent.

<Steps>
  <Step title="Install and open">
    On a fresh install, the chat screen shows the **"Add an API key to start"** panel, a one-sentence explanation of what the app does, and an **"Open settings"** button — not a blank screen and not a raw SDK error. See [Empty Chat](/docs/features/mobile/empty-chat).
  </Step>

  <Step title="Paste a key and return to Chat">
    After pasting an OpenAI key in [API Keys](/docs/features/mobile/api-keys) and returning to Chat, the panel switches to the welcome copy — **"Ask something to begin."** and one line saying what the app does. The chat is ready.
  </Step>
</Steps>

***

## Best Practices

<AccordionGroup>
  <Accordion title="Run npm run check before every commit">
    The bundle gate catches Node builtins and top-level `process.env` that pass in Node but blank the webview on device.
  </Accordion>

  <Accordion title="Use remote-http for the desktop dev flow">
    The first-launch default on a device is now the in-process engine (`praisonai-ts`). For iterating on a laptop, switch to `remote-http` in Settings: it speaks the full 11-event vocabulary against a running desktop engine, so you see tool rows and approvals while you work. The persisted choice wins, so the switch sticks.
  </Accordion>

  <Accordion title="Keep the engine choice in settings">
    `engineId` is read from settings at boot, so users switch runtimes without a rebuild.
  </Accordion>
</AccordionGroup>

***

## Related

<CardGroup cols={2}>
  <Card title="Agent Engine Port" icon="plug" href="/docs/features/mobile/engines">
    The three shipped engines and the conformance harness.
  </Card>

  <Card title="The Two Seams" icon="layer-group" href="/docs/features/mobile/architecture">
    Why the boundaries are enforced by build.
  </Card>

  <Card title="Shipping to Stores" icon="mobile-screen-button" href="/docs/features/mobile/shipping-to-stores">
    The CSP, WebView floor, and monotonic versioning story.
  </Card>

  <Card title="Empty Chat" icon="message-square-dashed" href="/docs/features/mobile/empty-chat">
    The first-launch panel and the four rules behind it.
  </Card>
</CardGroup>

**Next:** Ready to ship to a store? See [Shipping to iOS and Android](/docs/features/mobile/shipping-to-stores) for the CSP, WebView floor, and monotonic versioning story.
