From odin
Encodes state machine specifications, invariants, and temporal properties before writing implementation code. Use for protocol implementations, workflow engines, and concurrent systems.
How this skill is triggered — by the user, by Claude, or both
Slash command
/odin:validation-firstThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Define state machines from requirements before implementation. Specifications say what the system MUST do. Encode compile-time properties in types first, then layer state machine modeling for properties types cannot express.
Define state machines from requirements before implementation. Specifications say what the system MUST do. Encode compile-time properties in types first, then layer state machine modeling for properties types cannot express.
Modern insight (2025): State machines exist on a spectrum from runtime enums to compile-time typestates. Use the strongest mechanism available. XState v5 introduces actor model semantics -- state machines are now first-class concurrent entities, not just enum switches.
See approaches for language-specific state machine mechanisms. See examples for brief state machine patterns per language. See formal-tools for specification and model checking tools.
| Level | Mechanism | Strength | Use When |
|---|---|---|---|
| Typestate (compile-time) | Generic type params, phantom data | Invalid transitions unrepresentable | Protocol APIs, builder patterns, Rust FFI |
| Statecharts (hierarchical) | Nested states, parallel regions | Complex workflows, entry/exit | Game state, multi-modal UI, XState |
| Flat FSM (runtime) | Enum + match/switch | Simple, auditable | Order lifecycle, connection mgmt |
| Actor model | Independent entities, message passing | Concurrent state | Distributed systems, Erlang/Elixir, XState v5 |
Default choice: Use the strongest mechanism the language supports. Typestate in Rust, sealed classes in Kotlin, discriminated unions in TypeScript.
Type system (strongest) > State machine > Contract > Runtime check (weakest)
{ isLoading: true, isError: true, data: X } -- contradictory states representable. Use discriminated unions instead.state: "pending" with no exhaustiveness checkSTATE MACHINE: <Name>
STATES: S1 | S2 | S3
VARIABLES: var1: type, var2: type
INIT: var1 = val, state = S1
ACTION name(args): PRE: guard -> POST: new_state, effects
INVARIANT: condition_that_always_holds
When state machines guard event-sourced aggregates:
| Gate | Pass Criteria | Blocking |
|---|---|---|
| Typecheck | No errors; exhaustive match where language enforces it | Yes |
| Invariants | All invariant assertions pass after each action | Yes |
| Tests | All state transition tests pass | If present |
| Code | Meaning |
|---|---|
| 0 | Specification verified, ready for implementation |
| 11 | Checker not available |
| 12 | Syntax/type errors in specification |
| 13 | Invariant violation detected |
| 14 | Specification tests failed |
| 15 | Implementation incomplete |
npx claudepluginhub outlinedriven/odin-claude-plugin --plugin odinDesigns finite state machines and statecharts for modeling entity lifecycles, workflows, and system behaviors using Harel semantics, PlantUML, and Mermaid notation.
Models complex UI flows as finite state machines with states, events, transitions, actions, and guards. Useful for forms, data fetching, authentication flows, and wizards.