Effect-native, schema-first, completely type-safe state machines and statecharts, inspired by XState.
The goal of
effect-machineis to become a core effect module.It originates from the following PR.
import{Machine}from"@typeonce/effect-machine"import{Effect,Schema}from"effect"constStates=Machine.states({Locked: {},Unlocked: {}})constEvents=Machine.events(Schema.TaggedUnion({Coin: {},Push: {}}))constTurnstile=Machine.make({id: "Turnstile",states: States.states,events: Events,initial: (to)=>to.Locked()}).handle({Locked: {on: {Coin: (to)=>to.full.Unlocked()}},Unlocked: {on: {Push: (to)=>to.full.Locked()}}})constprogram=Effect.gen(function*(){constref=yield*Machine.start(Turnstile)yield*ref.send(Events.Coin())})State and event schemas define the protocol. The handler tree defines the statechart, and the result runs as an Effect-managed machine.
The workspace publishes four packages at the same version:
@typeonce/effect-machinecontains the machine runtime, testing modules, and documentation.@typeonce/effect-machine-reactowns machine atoms in React without subscribing their owners to machine state.@typeonce/effect-machine-devtoolscontains the publishable local machine visualizer and CLI.@typeonce/oxlint-plugin-effect-machinechecks Effect Machine models for common structural mistakes.
Install matching versions so the runtime, devtools, and lint rules stay aligned.
XState is the project's main inspiration and reference for statechart semantics and API coverage.
Direct API comparisons exposed gaps in Effect Machine, and benchmarks against XState drove many runtime performance improvements. effect-machine is not a direct XState replacement.