Installation
gpui-query is a Cargo crate. This page covers adding it to a GPUI project, choosing the right feature flags, and installing a QueryClient as a GPUI Global so the hooks can share a single cache.
Add the dependency
Section titled “Add the dependency”Run cargo add in your crate:
cargo add gpui-queryor add it by hand to Cargo.toml:
[dependencies]gpui-query = "0.2.0"Feature flags
Section titled “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. |
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:
[dependencies]gpui-query = { version = "0.2.0", features = ["hook"] }cargo add gpui-query --features hookYou 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
Section titled “Companion crates”Two standalone crates extend gpui-query without adding dependencies to the core:
gpui-query-persistis a reference disk adapter.FilePersisteratomically writes aPersistSnapshotto disk (JSON or bincode) with a tolerant load.cargo add gpui-query-persist. See Persistence: reference adapter.gpui-query-httpturns a server’sCache-Controlheader into aCachePolicy(“server wins”) and layers an in-memoryHttpCacheover any HTTP backend.cargo add gpui-query-http. See HTTP cache headers.
Both depend on gpui-query with a narrow feature set and publish independently.
Set up the QueryClient
Section titled “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.
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:
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);Verify it is reachable
Section titled “Verify it is reachable”From any context, read the client back to confirm the global is set:
# 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 shows your first end-to-end query.
Next steps
Section titled “Next steps”- Quick Start: define a fetcher, call
use_query, render data. - Queries: the full
use_querysurface andQueryResourceaccessors. - Caching:
CachePolicy, deduplication, and GC in depth.