From harness-claude
Defines statecharts with XState's createMachine for explicit states, transitions, context, and events. Useful for modeling complex UI flows and preventing illegal state transitions.
How this skill is triggered — by the user, by Claude, or both
Slash command
/harness-claude:xstate-machine-definitionThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
> Define statecharts with createMachine for explicit states, transitions, context, and events
Define statecharts with createMachine for explicit states, transitions, context, and events
isLoading && !isError && isSubmitted) with named states.machine.ts file. Keep it separate from UI components.Context (extended state data) and Events (a discriminated union of all possible events).createMachine with id, initial, context, and states. Each state has on for transitions.idle, loading, error), not verbs.SUBMITTED, LOADED, ERRORED) or imperative commands (SUBMIT, RETRY).target for the destination state. Omit target for self-transitions that only run actions.// auth.machine.ts
import { createMachine, assign } from 'xstate';
interface AuthContext {
user: { id: string; name: string } | null;
error: string | null;
retries: number;
}
type AuthEvent =
| { type: 'LOGIN'; email: string; password: string }
| { type: 'LOGOUT' }
| { type: 'RETRY' }
| { type: 'done.invoke.authenticate'; data: { id: string; name: string } }
| { type: 'error.platform.authenticate'; data: Error };
const authMachine = createMachine<AuthContext, AuthEvent>({
id: 'auth',
initial: 'idle',
context: {
user: null,
error: null,
retries: 0,
},
states: {
idle: {
on: {
LOGIN: 'authenticating',
},
},
authenticating: {
invoke: {
id: 'authenticate',
src: 'authenticateUser',
onDone: {
target: 'authenticated',
actions: assign({ user: (_, event) => event.data, error: null }),
},
onError: {
target: 'error',
actions: assign({
error: (_, event) => event.data.message,
retries: (ctx) => ctx.retries + 1,
}),
},
},
},
authenticated: {
on: {
LOGOUT: {
target: 'idle',
actions: assign({ user: null }),
},
},
},
error: {
on: {
RETRY: {
target: 'authenticating',
guard: 'canRetry',
},
LOGIN: 'authenticating',
},
},
},
});
export { authMachine };
Context vs state: "State" in XState means the finite state node (idle, loading, error). "Context" is the extended state — arbitrary data that travels with the machine. Use finite states for mode/phase, context for data.
XState v5 changes: If using XState v5, the API shifts to setup().createMachine() with a different structure:
import { setup, assign } from 'xstate';
const machine = setup({
types: {} as {
context: AuthContext;
events: AuthEvent;
},
guards: { canRetry: ({ context }) => context.retries < 3 },
actions: { clearUser: assign({ user: null }) },
}).createMachine({
id: 'auth',
initial: 'idle',
context: { user: null, error: null, retries: 0 },
states: {
/* ... */
},
});
State node types:
atomic — leaf node, no child states (default)compound — has child states (nested)parallel — all child states active simultaneouslyfinal — terminal state, triggers onDone in the parenthistory — remembers the last active child stateDesign principles:
https://stately.ai/docs/machines
npx claudepluginhub intense-visions/harness-engineering --plugin harness-claudeGenerates full type safety for XState machines using the v5 setup pattern or v4 typegen. Helps with TypeScript errors on event types, guards, and actions.
Models complex UI flows as finite state machines with states, events, transitions, actions, and guards. Useful for forms, data fetching, authentication flows, and wizards.
Designs finite state machines and statecharts for modeling entity lifecycles, workflows, and system behaviors using Harel semantics, PlantUML, and Mermaid notation.