Skip to main content
Reading application state is what separates a verdict from a screenshot. A 200 proves the server was reachable. A rendered row proves React ran. Only state proves your app accepted the change. Reticle needs one thing from your store: a way to read it, and a way to know when it changed.

The contract

Anything with that shape registers directly, with no adapter.
Pass the store, not () => store.getState(). The store form wires subscribe, so every mutation emits a state diff. The getter form still works for compatibility but leaves the store on pull-only reads: no change events, and an empty stateDiffs in every verdict.That reads as “nothing changed” and actually means “I was never watching”. It is the most common instrumentation mistake there is.

Works natively

Zustand

A zustand hook already has getState and subscribe. Pass it straight in.

Redux

A Redux store is StoreLike by definition. Same one-liner.
This is what the Reticle fixture app does, and it is why its verdicts carry stateDiffs: [{ "path": "auth", "from": null, "to": "…" }].

Adapters

Eight libraries do not fit StoreLike for a reason specific to each. Every adapter returns a StoreLike you hand straight to registerStore. Each example below is the one documented in the adapter’s own source.

TanStack Query

Register your server cache even if you already register a client store. “The screen is plausible and the network is silent” is the normal failure with query caches: a mutation forgets to invalidate, the UI keeps rendering a number that was true a minute ago, and nothing fires for anyone to notice. The cache’s freshness metadata is the only witness.

Pinia

Svelte stores

Jotai

Atoms are not a store, so you name the ones you care about.

Valtio

MobX

You pass toJS and reaction in rather than Reticle importing MobX. The SDK stays free of your state library, and your bundle stays free of a copy it did not ask for.

XState

An XState actor’s subscribe returns a subscription object rather than an unsubscribe function, which is the single reason it does not satisfy StoreLike already.

Recoil

The most involved, because Recoil has no store object to hand over.

Anything else

pushStore gives you a store plus the push that updates it, so you own the write side. Useful for state that lives somewhere Reticle cannot reach: a web worker, a websocket, a third-party SDK.

Reading it back

reticle_state walks a dot-path with numeric array indices. depth collapses anything deeper to a size marker, which is the difference between a cheap look and a very expensive one on a large store. You can also assert on it directly, which is stronger than reading it afterwards:
That catches a UI-versus-store desync, a deploy that only looks shipped, deterministically and with no model involved.

reticle_state

Arguments, depth control, and reading a component’s hook state.

Instrument your app

Stores are one of three things worth registering. The other two are signals and testids.
Last modified on August 14, 2026