# Installation

Install gpui-query in a Rust GPUI app: add the crate, register the global QueryClient, and verify your setup with a first query.

gpui-query is a Cargo crate. This page covers adding it to a GPUI project, choosing the right [feature flags](#feature-flags), and installing a `QueryClient` as a GPUI [`Global`](/docs/api/query-client) so the hooks can share a single cache.

## Add the dependency

Run `cargo add` in your crate:

```sh
cargo add gpui-query
```

or add it by hand to `Cargo.toml`:

```toml
[dependencies]
gpui-query = "0.2.0"
```

> `gpui-query` depends on `gpui` as a workspace dependency. It does not ship `gpui` itself. Your app already brings `gpui` in, and gpui-query links against the same version.

## Feature flags

The crate is split into four layers, each behind a feature flag:

| Feature  | Default | Pulls in                                            | What it gives you                                  |
| -------- | ------- | --------------------------------------------------- | -------------------------------------------------- |
| `core`   | no      | `serde` only                                        | The transport-agnostic state machine (`QueryResource`, `CachePolicy`, …) with no GPUI dependency. Usable in non-GPUI code or tests. |
| `client` | yes     | `core` + `gpui`                                     | The `QueryClient` registry and its type-partitioned buckets. |
| `hook`   | no      | `client`                                            | The `use_query` / `use_mutation` hooks you call from views. |
| `persist` | no     | `client` + `hook` + `serde_json` + `thiserror`      | Async persistence: the `Persister` trait, `QueryClient::persist_with`, the free `hydrate` function, and the typed (de)serializer registries. See [Persistence](/docs/guides/persistence). |

`client` is on by default, so `cargo add gpui-query` is enough to get the registry. To use the ergonomic hooks from your components, enable the `hook` feature:

```toml
[dependencies]
gpui-query = { version = "0.2.0", features = ["hook"] }
```

```sh
cargo add gpui-query --features hook
```

You almost always want `hook` in an application. Reach for `core` alone when you need the state machine without a GPUI dependency (a library, a CLI that reasons about cached state, or unit tests). Add `persist` when you want to save and restore the cache across restarts (`gpui-query = { features = ["hook", "persist"] }`).

## Companion crates

Two standalone crates extend gpui-query without adding dependencies to the core:

- **`gpui-query-persist`** is a reference disk adapter. `FilePersister` atomically writes a `PersistSnapshot` to disk (JSON or bincode) with a tolerant load. `cargo add gpui-query-persist`. See [Persistence: reference adapter](/docs/guides/persistence#reference-adapter-filepersister).
- **`gpui-query-http`** turns a server's `Cache-Control` header into a `CachePolicy` ("server wins") and layers an in-memory `HttpCache` over any HTTP backend. `cargo add gpui-query-http`. See [HTTP cache headers](/docs/guides/http-caching).

Both depend on `gpui-query` with a narrow feature set and publish independently.

## Set up the QueryClient

`QueryClient` is a GPUI `Global`. Install it once during app setup. From then on, every hook routes resource creation through it for shared caching, deduplication, and garbage collection.

```rust
use gpui_query::client::QueryClient;

fn setup_app(cx: &mut gpui::App) {
    cx.set_global(QueryClient::new());
}
```

`QueryClient::new()` uses the default policies (`Ttl { ttl_ms: 60_000 }`, `LatestWins`). Override them with `with_policies` and tune the garbage-collection window with `with_gc_time`:

```rust
use gpui_query::client::QueryClient;
use gpui_query::{CachePolicy, core::RequestPolicy};

let client = QueryClient::with_policies(
    CachePolicy::Ttl { ttl_ms: 60_000 },
    RequestPolicy::LatestWins,
)
.with_gc_time(600_000); // 10 minutes (default is 5)

cx.set_global(client);
```

> If a hook runs before a `QueryClient` is installed, it falls back to creating a standalone entity. There is no shared cache, deduplication, or GC. Always install the client during app startup.

## Verify it is reachable

From any context, read the client back to confirm the global is set:

```rust
# use gpui_query::client::QueryClient;
# fn doc(cx: &gpui::App) {
let _client = cx.global::<QueryClient>();
# }
```

That is the entire setup: add the crate, enable `hook`, install a `QueryClient` global. With that in place, the [Quick Start](/docs/getting-started/quick-start) shows your first end-to-end query.

## Next steps

- [Quick Start](/docs/getting-started/quick-start): define a fetcher, call `use_query`, render data.
- [Queries](/docs/api/queries): the full `use_query` surface and `QueryResource` accessors.
- [Caching](/docs/guides/caching): `CachePolicy`, deduplication, and GC in depth.
