This tool works with both Expo and React Native CLI projects. Just install and go.
Testing a checkout flow means building the same state over and over: clear the cart, add ten items, navigate to checkout, test, repeat. Every iteration pays the setup cost again. Reproduced a bug that only happens with specific state? One wrong tap and you're rebuilding it from scratch.
Time Machine is macOS-style restore points for your app's client state: capture everything — device storage (AsyncStorage, MMKV, SecureStore), Redux, Zustand, Jotai, and the React Query cache — as a named snapshot, then restore it in one tap. Set up your test state once; jump back to it as many times as you want.
Don't take our word for it — this is the real tool, running right here, loaded with mock restore points. The guided tour below walks one debugging story: a checkout state gets captured, nine things drift, you open the values, see what restore can't apply and why, then restore in reload mode and watch the restore points come back with the app. Or skip the tour and just start tapping:
Not a video — this is the shipped tool on mock data. Watch a restore point get captured: storage, Redux, Zustand and the query cache, under one name.
npm install @buoy-gg/time-machineThat's it — auto-discovery finds the installed package and the TIME MACHINE tool appears in your floating menu:
import { FloatingDevTools } from "@buoy-gg/core";
export default function App() {
return (
<>
<YourApp />
<FloatingDevTools />
</>
);
}
import { FloatingDevTools } from "@buoy-gg/core";
export default function App() {
return (
<>
<YourApp />
<FloatingDevTools />
</>
);
}
Each state source is captured through the Buoy tool that already watches it — install the ones you use (@buoy-gg/storage, @buoy-gg/redux, @buoy-gg/zustand, @buoy-gg/jotai, @buoy-gg/react-query) and they register as snapshot sources automatically. The tool shows you exactly which sources can capture and restore, and why when one can't.
| Source | Restore mechanism |
|---|---|
| AsyncStorage | Diff: keys missing from the snapshot are removed, snapshot entries bulk-written. Buoy's own keys are never touched. |
| MMKV | Per registered instance, per-key diff. Read-only instances and ArrayBuffer values are skipped (and reported). |
| SecureStore | Registered keys written back with their original options. Biometric-protected keys are never read or written. |
| Redux | A single full-state jump through Buoy's reducer wrapper, verified after dispatch. Works with the zero-config enhancer, or wrap your root reducer in withBuoyDevTools() when using the middleware. |
| Zustand | Full setState(state, true) replace — with your store's action functions re-grafted from the live store first, so useStore(s => s.increment) keeps working. |
| Jotai | Every watched, writable atom is set individually. Derived atoms are captured for inspection and left to recompute. |
| React Query | Per-query diff against the live cache: existing queries get their state set (observers stay attached, with their real queryFns), missing ones are rebuilt, extras removed. Mutations aren't replayable, so the mutation cache is cleared. |
Honest limits: this is client state — your backend doesn't time-travel, so a restored cart is only as valid as the server allows. Component-local useState, navigation stacks, and in-flight requests aren't captured. Sources that can't fully restore say so up front, in the tool.