Retree is a lightweight and simple state management library, designed primarily for React. If you know how to work with objects in JavaScript or TypeScript, you pretty much already know how to use Retree.
import { Retree } from "@retreejs/core";
import { useNode } from "@retreejs/react";
const project = Retree.root({
tasks: [{ title: "Write docs", done: false }],
});
function TaskRow({ task }: { task: { title: string; done: boolean } }) {
const state = useNode(task); // re-renders only when this task changes
return (
<label>
<input
type="checkbox"
checked={state.done}
onChange={() => (state.done = !state.done)}
/>
{state.title}
</label>
);
}Full documentation, live playgrounds, and guides live at retree.dev.
Add Retree to an existing project with the interactive installer:
npm create @retreejs@latestIt detects React and Convex in your project, preselects the matching integrations, and can install the Retree AI skill for coding agents. In React + ESLint + TypeScript projects it also offers the Retree observation rule and can update eslint.config.mjs for you. pnpm create @retreejs and yarn create @retreejs work too. Then start with the Quickstart guide.
Retree needs zero build configuration — Retree.root, the React hooks, ReactiveNode with its dependencies getter, and this.memo(...) all work out of the box. Only authoring the @-prefixed decorators (@memo, @fnMemo, @select, @ignore, @link) in your own code requires standard (TC39 2023-11) decorator support:
- TypeScript 5+: works with no config, as long as
experimentalDecoratorsis not set. Legacy decorator semantics are incompatible — Retree's decorators detect them and throw an error explaining the fix. - Babel toolchains: add
@babel/plugin-proposal-decoratorswith{ "version": "2023-11" }.
Each decorator has a non-decorator equivalent (this.memo(...), the dependencies getter with this.dependency(...), Retree.link(...)). Full guide: Setup & decorators.
@retreejs/coreprovides Retree's proxy, event, memo,ReactiveNode, effect, and undo-history primitives.@retreejs/reactprovides React hooks for rendering Retree nodes, a provider for per-request SSR roots, and testing utilities.@retreejs/queryis the backend-agnostic async-query layer:QueryNode, fetch adapters, optimistic updates, and reconciliation over any subscription source.@retreejs/convexconnects Convex queries, paginated queries, actions, mutations, auth, and connection state to Retree nodes.@retreejs/react-convexadapts Convex'sConvexReactClientfor React apps that want one client instance for both Convex React and Retree, plus a Next.js RSC preload helper.@retreejs/devtoolsbridges Retree to the Redux DevTools Extension and exposes a structured change-log tap.@retreejs/react-eslint-plugincatches React render reads that go beyond the Retree node a component observes.
Core:
Retree.rootmakes one object the root of a Retree-managed tree. Use it once where plain state enters Retree.Retree.onsubscribes tonodeChanged,treeChanged, ornodeRemoved. Use it outside React and inside integrations.Retree.selectis the non-React version ofuseSelect. Use it to narrow notifications; it is not a cache.Retree.effectruns a function immediately and re-runs it whenever a tracked dependency changes — the third subscription primitive next toonandselect.createUndoHistoryrecords every change under a root into undo/redo steps;Retree.applyInverse/Retree.applyChangesare the underlying primitives.Retree.parentreturns the structural parent of a node. Use it for tree-local operations like deleting yourself from a list.Retree.move,Retree.link/@link, andRetree.clonemake ownership explicit: transfer, point without reparenting, or copy.Retree.isNodechecks whether a value is a Retree-managed node. Use it to guardRetree.rawwhen a value may be managed or plain.Retree.raw,Retree.managed,Retree.peekInto, andRetree.untrackedenable native-speed, proxy-free reads. Raw subtrees are guaranteed proxy-free.Retree.runTransactionbatches synchronous writes into one listener flush per changed node.Retree.runSilentperforms writes without emitting listeners.Retree.registerRootNamenames a root for tooling — debug taps and devtools label trees with it.ReactiveNodelets nodes emit from declareddependencies, with@selectgetters,memo/@memo/@fnMemocaching,@ignoreopt-outs, lifecycle hooks, andprepareTree.
React:
useRootcreates one Retree root for a React component lifetime.useNodere-renders a component for directnodeChangedevents on one node. Use it for rows, panels, forms, and focused child components.useTreere-renders fortreeChangedevents from a node or any descendant. Use it sparingly for small subtrees.useSelectre-renders only when a selected value or ordered dependency list changes.useRawsubscribes likeuseNodebut returns[raw, toManaged]for native-speed, proxy-free render reads.RetreeProvider/createRetreeContextprovide per-request roots for SSR apps and per-render roots for tests, instead of module singletons.@retreejs/react/testingshipscreateTestRoot(auto listener cleanup) andactOnRetree(act-wrapped writes) for component tests.@retreejs/react-eslint-pluginprovides a typed ESLint preset that catches provably unobserved Retree reads in React components.
Data:
QueryNodeandfetchQueryNodesubscribe any async backend into Retree state with a status machine,keepPreviousData,retry(), optimistic updates, and reconciliation.ConvexNodeand friends bind Convex live queries, paginated queries, mutations with optimistic updates, auth state, and SSR preload to Retree.connectReduxDevToolsandcreateChangeLogTapinspect every write in the Redux DevTools Extension or your own tooling.
Published Retree npm packages include their package README.md and the root llms.txt file so sandboxed agents can read the high-signal Retree guide directly from an installed package. The website serves every guide as raw markdown too (see retree.dev/llms.txt).
This repository also exposes a Retree agent skill at skills/retree/SKILL.md, with full markdown references generated from the docs sources into skills/retree/references/. npm run docs refreshes those references after the TypeDoc site builds. Agents that support the open skills CLI can install or use it with:
npx skills add ryanbliss/retree --skill retree
npx skills use ryanbliss/retree@retreeThe primary API reference is generated from source on every deploy at retree.dev/api. To generate the TypeDoc site locally instead:
npm run docsThe generated static site is written to docs/ and ignored by Git.
Docs are hosted at https://www.retree.dev.
Copyright (c) Ryan Bliss. All rights reserved. Licensed under MIT license.
Credit to Fluid Framework's new SharedTree feature, which has served as a major inspiration for this project. If you want to use collaborative objects, I recommend checking out Fluid Framework!