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

# Installation

> Add whatsapp-rust to your Rust project

## Prerequisites

Before installing whatsapp-rust, ensure you have:

* **Rust nightly** (default) — required for Rust edition 2024 and SIMD-optimized binary protocol. The project pins `nightly-2026-04-05` via `rust-toolchain.toml`. See [Using stable Rust](#using-stable-rust) if you need stable toolchain support.
* **Cargo** package manager

<Note>
  SQLite is bundled by default with the `whatsapp-rust-sqlite-storage` crate, so you don't need to install it separately. If you prefer to link against a system-installed SQLite, disable the default `bundled-sqlite` feature.
</Note>

## Add to your project

`whatsapp-rust` re-exports the entire stack (`wacore`, `wacore_binary`, `waproto`, and all bundled implementations), so **one dependency line is enough** for most projects:

```toml Cargo.toml theme={null}
[dependencies]
whatsapp-rust = "0.6"
tokio = { version = "1.48", features = ["macros", "rt-multi-thread"] }
```

Every sub-crate path is reachable through the main crate:

* `whatsapp_rust::waproto::whatsapp` (aliased as `wa` in `prelude`)
* `whatsapp_rust::wacore`, `whatsapp_rust::wacore_binary`
* `whatsapp_rust::store::SqliteStore`, `whatsapp_rust::http::UreqHttpClient`, `whatsapp_rust::transport::TokioWebSocketTransportFactory`

`whatsapp-rust` also re-exports every third-party crate whose types appear in its public API, so you never need to add or version-pin any of these yourself:

* `whatsapp_rust::buffa` — sub-message fields on `wa::Message` (`MessageField`; also re-exported directly from `prelude`) — see [waproto](/api/waproto)
* `whatsapp_rust::anyhow` — the error type on the store/transport/`InboundDurabilityHook` traits
* `whatsapp_rust::async_trait` — the macro required to implement those traits
* `whatsapp_rust::bytes` — `Transport::send` payloads
* `whatsapp_rust::chrono` — timestamps returned by `wacore::time` and message metadata
* `whatsapp_rust::futures` — the `oneshot::Receiver` returned by response-waiting accessors
* `whatsapp_rust::serde`, `whatsapp_rust::serde_json`, `whatsapp_rust::async_channel`

<Note>
  This is purely additive — you can still add any of these crates directly (for example to pin your own version, or to use APIs beyond what whatsapp-rust re-exports).
</Note>

The same holds for git consumers — no need to pin every sibling crate:

```toml Cargo.toml theme={null}
[dependencies]
whatsapp-rust = { git = "https://github.com/oxidezap/whatsapp-rust", rev = "<commit>" }
tokio = { version = "1.48", features = ["macros", "rt-multi-thread"] }
```

If you need to declare a sibling crate explicitly (for example to enable a crate-specific feature flag), you can still add it individually. The full multi-crate form:

<CodeGroup>
  ```toml Nightly (default) theme={null}
  [dependencies]
  whatsapp-rust = "0.6"
  # Only needed for crate-specific features not exposed through whatsapp-rust:
  # whatsapp-rust-sqlite-storage = "0.6"
  # whatsapp-rust-tokio-transport = "0.6"
  # whatsapp-rust-ureq-http-client = "0.6"
  # wacore = "0.6"
  # waproto = "0.6"
  tokio = { version = "1.48", features = ["macros", "rt-multi-thread"] }
  ```

  ```toml Stable Rust theme={null}
  [dependencies]
  whatsapp-rust = { version = "0.6", default-features = false, features = [
      "sqlite-storage",
      "tokio-transport",
      "tokio-runtime",
      "ureq-client",
      "tokio-native",
      "signal",
  ] }
  wacore = { version = "0.6", default-features = false }
  tokio = { version = "1.48", features = ["macros", "rt-multi-thread"] }
  ```
</CodeGroup>

## Feature flags

whatsapp-rust supports several optional features:

| Feature                  | Description                                                                                                                                                                                                                                                                          | Included by default |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------- |
| `tokio-runtime`          | Enables `TokioRuntime` implementation of the `Runtime` trait. Also required for `TypedCache::invalidate_all()` on custom cache backends                                                                                                                                              | ✅ Yes               |
| `tokio-native`           | Multi-threaded Tokio runtime (`tokio/rt-multi-thread`)                                                                                                                                                                                                                               | ✅ Yes               |
| `tokio-transport`        | Tokio WebSocket transport                                                                                                                                                                                                                                                            | ✅ Yes               |
| `ureq-client`            | Ureq HTTP client                                                                                                                                                                                                                                                                     | ✅ Yes               |
| `sqlite-storage`         | SQLite storage backend                                                                                                                                                                                                                                                               | ✅ Yes               |
| `simd`                   | SIMD-optimized binary protocol encoding/decoding (**requires nightly Rust**)                                                                                                                                                                                                         | ✅ Yes               |
| `signal`                 | Unix signal handling (graceful shutdown on SIGTERM/Ctrl+C)                                                                                                                                                                                                                           | ✅ Yes               |
| `tracing`                | Emit `tracing` spans/events across connect, send, receive, IQ, app state, pairing, media, and session flows. See [Observability](/advanced/observability)                                                                                                                            | ❌ No                |
| `tracing-pii`            | Render raw phone numbers in `tracing` fields instead of redacted `pn#<token>`. Local debugging only — never enable in production                                                                                                                                                     | ❌ No                |
| `metrics`                | Emit `wa_*` counters, histograms, and gauges through the [`metrics`](https://docs.rs/metrics) facade for Prometheus/OTLP dashboards. See [Metrics](/advanced/metrics)                                                                                                                | ❌ No                |
| `client-lifecycle`       | Low-level, generation-scoped extension lifecycle seam (`ClientLifecycle`, `ConnectionScope`). Enabled automatically by `plugins`; enable it directly only if you need lifecycle hooks without the full native plugin host. **Requires git source — not in published 0.6**            | ❌ No                |
| `plugins`                | Build-time native plugin host: type-safe `ClientPlugin` registration through `ClientBuilder`, capability-scoped APIs, and generation-scoped task lifecycle. Enables `client-lifecycle`. **Requires git source — not in published 0.6** (see [Native plugins](/advanced/plugins))     | ❌ No                |
| `voip`                   | 1:1 voice and video calls, full profile: bundled MLow + libopus codec adapters, codec-neutral H.264 video plane, E2E-SRTP encryption, relay transport. Alias for `voip-mlow` + `voip-libopus`. **Requires git source — not in published 0.6** (see [VoIP Calls](/guides/voip-calls)) | ❌ No                |
| `voip-runtime`           | Internal base feature enabled by every `voip-*` feature below (Tokio driver, relay transport, DTLS/SCTP). Not meant to be named directly — pick `voip-encoded` or a codec feature instead. **Requires git source — not in published 0.6**                                            | ❌ No                |
| `voip-encoded`           | Narrower `voip` profile: relay transport and encoded-audio boundary only, no bundled codec — supply raw Opus/MLOW packets from your own encoder/decoder. **Requires git source — not in published 0.6**                                                                              | ❌ No                |
| `voip-mlow`              | `voip-encoded` plus the bundled pure-Rust MLOW codec. **Requires git source — not in published 0.6**                                                                                                                                                                                 | ❌ No                |
| `voip-libopus`           | `voip-encoded` plus the optional libopus FFI codec adapter. **Requires git source — not in published 0.6**                                                                                                                                                                           | ❌ No                |
| `danger-skip-tls-verify` | Skip TLS verification (unsafe)                                                                                                                                                                                                                                                       | ❌ No                |
| `debug-snapshots`        | Debug protocol snapshots                                                                                                                                                                                                                                                             | ❌ No                |

<Tip>
  All default features enable Tokio as the async runtime, but every component is optional. To target a different runtime (async-std, WASM, etc.), disable all defaults and provide your own implementations of the `Runtime`, `TransportFactory`, `HttpClient`, and `Backend` traits. See [custom backends](/guides/custom-backends) for details.
</Tip>

The `wacore` crate has an additional feature for WASM browser targets:

| Feature | Description                                                                                      | Included by default |
| ------- | ------------------------------------------------------------------------------------------------ | ------------------- |
| `js`    | Enables browser-compatible random number generation via `getrandom/wasm_js` for `wasm32` targets | ❌ No                |

To use whatsapp-rust in a WASM browser environment, enable the `js` feature on `wacore`:

```toml Cargo.toml theme={null}
[dependencies]
wacore = { version = "0.6", default-features = false, features = ["js"] }
```

The `waproto` crate has its own feature flags:

| Feature             | Description                                                                                                                     | Included by default |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------- | ------------------- |
| `serde-deserialize` | Adds `Deserialize` derive and `#[serde(default)]` to all protobuf types                                                         | ❌ No                |
| `serde-snake-case`  | Accepts snake\_case enum variant names during deserialization (implies `serde-deserialize`)                                     | ❌ No                |
| `serde-enum-repr`   | Enums (de)serialize as their numeric repr instead of the variant name — what the JS/WASM bridge and camelCase serializer expect | ❌ No                |

`build.rs` always runs and generates `whatsapp.rs` into `OUT_DIR` — you do not need any feature flag for normal builds. All protobuf types derive `Serialize` by default. Enable `serde-deserialize` when you need to parse protobuf types from JSON (e.g., in a WASM bridge). Enable `serde-snake-case` when your JSON source uses snake\_case for enum variants (buffa generates SCREAMING\_SNAKE\_CASE by default).

```toml Cargo.toml theme={null}
[dependencies]
waproto = { version = "0.6", features = ["serde-snake-case"] }
```

The `whatsapp-rust-sqlite-storage` crate has its own feature flags:

| Feature          | Description                                                     | Included by default |
| ---------------- | --------------------------------------------------------------- | ------------------- |
| `bundled-sqlite` | Bundles SQLite (compiles from source, no system library needed) | ✅ Yes               |

To use a system-installed SQLite instead of the bundled version:

```toml Cargo.toml theme={null}
[dependencies]
whatsapp-rust-sqlite-storage = { version = "0.6", default-features = false }
```

The optional `whatsapp-rust-chat-store` crate — an event-sourced SQLite chat/message history store, not re-exported through `whatsapp-rust` — has its own feature flag:

| Feature  | Description                          | Included by default |
| -------- | ------------------------------------ | ------------------- |
| `search` | SQLite FTS5 full-text message search | ❌ No                |

```toml Cargo.toml theme={null}
[dependencies]
whatsapp-rust-chat-store = "0.1"
```

To enable full-text search, turn on the `search` feature:

```toml Cargo.toml theme={null}
[dependencies]
whatsapp-rust-chat-store = { version = "0.1", features = ["search"] }
```

See [Chat Store](/api/chat-store) for the full API.

<Note>
  The default features provide everything needed for most use cases. Only customize features if you have specific requirements.
</Note>

## Using stable Rust

By default, whatsapp-rust uses Rust **edition 2024** and enables the `simd` feature, which uses Rust's `portable_simd` API for optimized binary protocol encoding/decoding. Both of these require a **nightly** Rust toolchain. The project pins `nightly-2026-04-05` via `rust-toolchain.toml`.

To compile on **stable Rust**, disable the `simd` feature by setting `default-features = false`. You must do this on **both** `whatsapp-rust` and `wacore` — otherwise Cargo's [feature unification](https://doc.rust-lang.org/cargo/reference/features.html#feature-unification) will re-enable SIMD through the `wacore` dependency:

```toml Cargo.toml theme={null}
[dependencies]
# Disable defaults (removes `simd`), then re-enable everything else
whatsapp-rust = { version = "0.6", default-features = false, features = [
    "sqlite-storage",
    "tokio-transport",
    "tokio-runtime",
    "ureq-client",
    "tokio-native",
    "signal",
] }
# wacore also needs default-features = false to prevent feature unification
# from re-enabling simd
wacore = { version = "0.6", default-features = false }

# These crates have no SIMD dependency — no changes needed
whatsapp-rust-sqlite-storage = "0.6"
whatsapp-rust-tokio-transport = "0.6"
whatsapp-rust-ureq-http-client = "0.6"
waproto = "0.6"
tokio = { version = "1.48", features = ["macros", "rt-multi-thread"] }
```

<Warning>
  Setting `default-features = false` only on `whatsapp-rust` is **not enough** if you also depend on `wacore` directly. The direct `wacore` dependency enables `simd` by default, and Cargo merges features across all dependents. Both must opt out.
</Warning>

The encoder/decoder automatically falls back to scalar code paths when SIMD is disabled. There is no functional difference — only a minor performance difference in binary protocol operations.

## 32-bit target support

whatsapp-rust uses [`portable-atomic`](https://crates.io/crates/portable-atomic) instead of `std::sync::atomic` for 64-bit atomic operations. This means the library works on **32-bit targets** (ARM32, MIPS, RISC-V 32, etc.) where `AtomicU64` is not natively available — `portable-atomic` provides a software fallback automatically.

No extra configuration is needed. The `portable-atomic` dependency is included with the `fallback` feature enabled by default across all crates (`whatsapp-rust`, `wacore`, and `whatsapp-rust-sqlite-storage`).

<Tip>
  If you're building for a 32-bit embedded target or cross-compiling to `armv7-unknown-linux-gnueabihf`, whatsapp-rust will compile and run correctly out of the box.
</Tip>

## Custom features example

If you want to use only specific features:

```toml Cargo.toml theme={null}
[dependencies]
whatsapp-rust = { version = "0.6", default-features = false, features = ["sqlite-storage", "tokio-transport"] }
```

## Verify installation

Create a simple test file to verify the installation:

```rust src/main.rs theme={null}
use whatsapp_rust::bot::Bot;

fn main() {
    println!("whatsapp-rust installed successfully!");
}
```

Run it with:

```bash theme={null}
cargo run
```

If you see "whatsapp-rust installed successfully!", you're ready to move on to the [Quickstart](/quickstart) guide.

## Docker deployment

whatsapp-rust ships a pre-built multi-arch image to GHCR and includes a Dockerfile for building your own. The runtime image is built from `scratch` (only the static binary) and runs unprivileged as uid 65532.

### Pre-built image

Pull from GitHub Container Registry — a single manifest resolves to `linux/amd64` or `linux/arm64` automatically based on the host:

```bash theme={null}
docker pull ghcr.io/oxidezap/whatsapp-rust:latest
```

Tagged releases are also available (e.g. `ghcr.io/oxidezap/whatsapp-rust:0.6.0`). The image is published on every push to `main`, on `v*` tags, and can be triggered manually via the Actions tab.

### Build from source

```bash theme={null}
docker build -t whatsapp-rust .
```

The build process:

1. Uses `rust:alpine` with [cargo-chef](https://github.com/LukeMathWalker/cargo-chef) (pinned to a fixed release with `--locked`) for efficient, reproducible dependency caching
2. Detects the host target triple at build time — `docker buildx build --platform linux/arm64` produces native binaries without Dockerfile changes
3. Enables `-Zshare-generics=y` (−5.6% `.text`) and recompiles `std` with the release profile (`-Zbuild-std`, −\~300 KiB more) so it participates in fat LTO — together these two flags reduce `.text` by roughly 8%; the full optimization series (#842–#845) achieved 15% total
4. Caches dependency compilation via `cargo chef cook --target` in a separate layer for fast rebuilds
5. Produces a final image from `scratch` containing only the binary

### Run the container

Use a **named volume** for `/data`. The container runs as uid 65532 and a named volume inherits that ownership automatically, so the SQLite database stays writable without extra setup:

```bash theme={null}
docker run -v whatsapp-data:/data ghcr.io/oxidezap/whatsapp-rust:latest
```

For pair code authentication, pass the `--phone` flag:

```bash theme={null}
docker run -v whatsapp-data:/data ghcr.io/oxidezap/whatsapp-rust:latest --phone 15551234567
```

<Note>
  **Host bind mounts** (e.g. `-v ./data:/data`) require the host directory to be owned by uid 65532, otherwise the container cannot write the database. Named volumes don't have this requirement.
</Note>

#### Upgrading from an older image

Images before this release ran as root. If an existing named volume has root-owned files, chown it once before restarting:

```bash theme={null}
docker run --rm -v whatsapp-data:/data alpine chown -R 65532:65532 /data
```

### Graceful shutdown

The container supports graceful shutdown out of the box. When the `signal` feature is enabled (it is by default), the bot listens for `SIGTERM` and `Ctrl+C`, disconnects cleanly from WhatsApp, and exits. Docker sends `SIGTERM` on `docker stop`, so the bot will shut down gracefully without losing session state.

Since the image is built from `scratch`, PID 1 is the binary itself. It handles signals directly — no init system like `tini` is needed. This matters more than usual for PID 1: the kernel silently drops any signal a PID-1 process has no handler installed for, so an unhandled `SIGTERM` doesn't just fall back to the default disposition — it's dropped entirely, and the process only stops once `docker stop`'s grace period expires and it's `SIGKILL`ed.

The bundled `demo` and `voip-cli` binaries get this via `whatsapp_rust::shutdown_signal()` — an exported async fn (gated on the `signal` feature) that resolves on the first of SIGINT or SIGTERM on Unix, or Ctrl+C elsewhere. Both handlers are armed before the future first suspends, so a signal arriving right after the first poll is still delivered. Use it in your own `main()` in place of a bare `tokio::signal::ctrl_c()` if you also deploy under Docker/Kubernetes/systemd:

```rust theme={null}
tokio::select! {
    _ = &mut handle => {}
    _ = whatsapp_rust::shutdown_signal() => {
        handle.shutdown().await;
    }
}
```

<Note>
  The Dockerfile detects the host target triple at build time via `rustc -vV`, so `docker buildx build --platform linux/arm64` (or any other supported platform) works natively without modifying the Dockerfile. The nightly-only build flags (`-Zshare-generics`, `-Zbuild-std`) apply only inside this image — stable consumers and local `cargo build` invocations are unaffected.
</Note>

## Next steps

<Card title="Quickstart" icon="rocket" href="/quickstart">
  Build your first WhatsApp bot in minutes
</Card>
