vscxml User Guide
Complete guide to the vscxml suite for generating, simulating, and designing W3C SCXML state machines.
Overview
vscxml is a professional development suite that transforms W3C SCXML (State Chart XML) specifications into executable, production-ready code for Java, JavaScript, C#, C, Python, Go, and Structured Text (IEC 61131-3) targets.
The Tools
vscxml consists of four integrated applications, each available for Windows, macOS, and Linux:
| Tool | Purpose | Documentation |
|---|---|---|
| VSCXML-Editor | Design state machines with drag-and-drop | Editor Guide |
| VSCXML-Simulator | Test and debug interactively | Simulator Guide |
| VSCXML-Generator-CLI | Generate production code via command line (scxml-gen) |
Generator Guide |
| VSCXML-Generator | Visual desktop app for code generation | Generator Guide |
Each tool installs separately and appears in your system's application menu. The VSCXML-Generator-CLI provides the scxml-gen command for terminal use, while the VSCXML-Generator desktop app offers a visual interface for the same functionality.
All tools also integrate with Claude Code and other LLM tools via the MCP Server (49 tools for AI-assisted state machine development).
Why vscxml?
| Feature | Benefit |
|---|---|
| Transpilation | Compiles SCXML to native code - no runtime parsing overhead |
| W3C Compliant | 100% ECMAScript datamodel compliance across all 6 targets |
| Multi-Platform | Single SCXML source generates Java, JavaScript, C#, C, Python, and Go code |
| Production Ready | Extensively tested with 2,600+ automated test cases |
| Embedded Support | C target runs on Arduino, ESP32, bare-metal microcontrollers |
Workflow
The recommended workflow for developing state machines:
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Visual Editor │────▶│ Simulator │────▶│ Generator │
│ (Design) │ │ (Test & Debug) │ │ (Build Code) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│ │ │
Create states Send events Output code
Add transitions Check behavior Java/JS/C#/C/
Define actions Debug issues Python/Go
1. Design
Use the Visual Editor to create your state machine:
- Drag and drop states onto the canvas
- Connect states with transitions
- Add actions for entry, exit, and transitions
- Export to
.scxmlformat
2. Test
Load your .scxml file in the Simulator:
- Send events and observe state changes
- Inspect variables in the datamodel
- Debug transitions with breakpoints
- Record traces for regression testing
3. Generate
Use the Code Generator to produce production code:
- Select target language (Java, JavaScript, C#, C, Python, Go, or Structured Text)
- Configure options (package name, output path, bundling)
- Generate code ready for your project
AI Integration (MCP)
vscxml integrates with Claude Code, Claude Desktop, Cursor, and other MCP-compatible AI tools through the @vscxml/mcp server. This gives AI assistants direct access to 49 tools for designing, simulating, generating, and visually editing state machines.
Setup (One Line)
claude mcp add vscxml -- npx -y @vscxml/mcp
Restart Claude Code after adding. All 49 VSCXML tools become available.
What You Can Do with AI
| Task | Example Prompt |
|---|---|
| Design | "Create a vending machine that accepts quarters and costs $1.25" |
| Simulate | "Test the vending machine by inserting 5 quarters" |
| Generate | "Generate Python and Java code for this state machine" |
| Visual Edit | "Push this to the editor and highlight the error states in red" |
| Export | "Export an interactive HTML demo I can share with my team" |
| Trace & Verify | "Record the simulation trace and compare it with the generated code's trace" |
The MCP server bridges all three backends (Generator, Simulator, Editor) and provides:
- Design tools — Create and validate SCXML from natural language
- Simulation tools — Run scenarios, set variables, record traces
- Code generation — Generate complete projects for all 7 targets
- Editor integration — Push diagrams, highlight states, add annotations, take screenshots
- Diagram editing — Add/remove states and transitions, set properties, clone states
- Export — SVG, PNG, interactive HTML player
See the MCP Setup Guide for full documentation and all 49 tools.
VSCXML-Generator Desktop App
The VSCXML-Generator is a visual desktop application for code generation. It provides the same functionality as the CLI but with a graphical interface powered by the built-in code generation server.
Features
- Visual code generation — Select target, configure options, and generate with a click
- Monaco editor — Built-in SCXML editor with syntax highlighting and validation
- Live preview — See generated code as you edit the SCXML source
- Multiple targets — Switch between Java, JavaScript, C#, C, Python, Go, and Structured Text
- Project generation — Generate complete runnable projects with build files and runtime libraries
How It Works
The desktop app bundles the VSCXML-Generator-CLI and starts it as a local REST API server. The React-based UI communicates with this server to provide a seamless visual experience.
VSCXML-Generator (Desktop App)
│
│ HTTP (localhost)
▼
VSCXML-Generator-CLI (REST Server)
│
▼
Generated Code (Java/JS/C#/C/Python/Go/ST)
The desktop app shares the same CLI installation. Updating the CLI updates both.
Installation
Preview installers are distributed through a private channel (GitHub Releases for invited evaluators only). To request access, email info@vscxml.com. General information and documentation are on the vscxml website. Each tool installs independently once you have a build.
System Requirements
| Platform | Requirements |
|---|---|
| Windows | Windows 10 or later (x64 or ARM64) |
| macOS | macOS 11 (Big Sur) or later (Intel & Apple Silicon) |
| Linux | Any modern distribution (AppImage or .deb) |
Installation Locations
| Platform | Location |
|---|---|
| Windows | %LOCALAPPDATA%\VSCXML-Editor\, %LOCALAPPDATA%\VSCXML-Simulator\, %LOCALAPPDATA%\VSCXML-Generator-CLI\ |
| macOS | /Applications/VSCXML-Editor.app, /Applications/VSCXML-Simulator.app, /Applications/VSCXML-Generator-CLI.app |
| Linux | AppImage (portable) or /opt/vscxml-*/ |
Verifying Installation
After installation, launch each tool from your system's application menu:
- VSCXML-Editor — Opens the visual state machine designer
- VSCXML-Simulator — Opens the interactive testing environment
- VSCXML-Generator-CLI — Opens a terminal shell with the
scxml-gencommand ready to use - VSCXML-Generator — Opens the visual code generation desktop app
The scxml-gen Command
The VSCXML-Generator-CLI installs a shell environment where scxml-gen is available. Launch it from your application menu to see:
╔═══════════════════════════════════════════════════════════════╗
║ VSCXML Generator CLI Shell ║
║ Code Generator for W3C SCXML State Machines ║
╠═══════════════════════════════════════════════════════════════╣
║ QUICK START: ║
║ scxml-gen <input.scxml> -t java -o Output.java ║
║ scxml-gen <input.scxml> -t javascript -o output.js ║
║ scxml-gen <input.scxml> -t c -o output.c ║
║ ║
║ TARGETS: java, javascript, csharp, c, python, go, st ║
║ OPTIONS: --code-only, --package, --bundle-auto, --help ║
╚═══════════════════════════════════════════════════════════════╝
MCP Server (AI Integration)
To use vscxml tools with Claude Code or other AI assistants:
claude mcp add vscxml -- npx -y @vscxml/mcp
See MCP Setup Guide for details.
Your First State Machine
Let's create a simple traffic light that cycles through red, green, and yellow.
For an interactive version of this example that runs in your browser, see the Traffic Light Tutorial.
Step 1: Design in the Editor
- Launch the VSCXML-Editor
- Create three states:
red,green,yellow - Add transitions:
red→greenon eventtimergreen→yellowon eventtimeryellow→redon eventtimer
- Set
redas the initial state - Save as
traffic.scxml
Step 2: Test in the Simulator
- Launch the VSCXML-Simulator from your application menu
- At the prompt, type:
load traffic.scxml - Type
start— observe "red" becomes active - Type
send timer— observe transition to "green" - Continue sending
timerevents to cycle through states
Step 3: Generate Code
Launch the VSCXML Generator and use the command line:
scxml-gen traffic.scxml -t java -o TrafficLight.java
Target Platforms
vscxml generates optimized code for seven platforms:
| Target | Typical Use | Documentation |
|---|---|---|
| Java | Server applications, Android, enterprise systems | Java Guide |
| JavaScript | Web browsers, Node.js, React/Vue apps | JavaScript Guide |
| C# | .NET applications, Unity games, cross-platform | C# Guide |
| C | Embedded systems, Arduino, ESP32, bare-metal | C Guide |
| Python | Data science, scripting, automation | Python Guide |
| Go | Cloud services, microservices, CLI tools | Go Guide |
| Structured Text | PLC programming, IEC 61131-3, CODESYS/TwinCAT | ST Guide |
Target Comparison
| Feature | Java | JS | C# | C | Python | Go | ST |
|---|---|---|---|---|---|---|---|
| W3C ECMAScript | 100% | 100% | 100% | 100% | 100% | 100% | N/A |
| Delayed events | Executor | setTimeout | Executor | Platform | Threading | Executor | TON timers |
| Thread safety | Built-in | Single | Built-in | Optional | Built-in | Built-in | PLC cycle |
| Invoke bundling | Runtime | --bundle | --bundle | --bundle | --bundle | --bundle | Static FBs |
See Target Platform Overview for detailed comparison.
Datamodels
The datamodel attribute determines how expressions and data are evaluated.
| Datamodel | Description | Best For |
|---|---|---|
null |
No data, only In() predicate |
Simple logic flows |
ecmascript |
Full JavaScript expressions | Complex scripting |
native-java |
Type-safe Java fields | Java applications |
native-js |
Native JavaScript objects | JS applications |
native-csharp |
Type-safe C# fields with LINQ | .NET applications |
native-c |
C variables | Embedded systems |
native-python |
Type-safe Python with type hints | Python applications |
native-go |
Type-safe Go with goroutines | Go applications |
native-st |
IEC 61131-3 typed variables | PLC applications |
Choosing a Datamodel
- Use
nullwhen you don't need variables - maximum portability - Use
ecmascriptfor complex expressions that work on all targets - Use
native-*for type-safe, target-specific code
See Datamodels Guide for detailed comparison.
Advanced Features
Invoke Children
Spawn child state machines from within a parent state. The Generator bundles them at compile time:
scxml-gen parent.scxml -t js --bundle-auto -o parent.js
Benefits:
- No runtime SCXML parsing
- Children run as compiled code
- Single output file
- Works offline/embedded
History States
Restore previous state configurations when re-entering a compound state:
<state id="editor">
<history id="editorHistory" type="deep"/>
<state id="editing">...</state>
<state id="preview">...</state>
</state>
Parallel States
Run multiple state regions concurrently:
<parallel id="dashboard">
<state id="clock">...</state>
<state id="weather">...</state>
<state id="notifications">...</state>
</parallel>
Delayed Events
Schedule events for future delivery:
<state id="waiting">
<onentry>
<send event="timeout" delay="5s" id="timeoutTimer"/>
</onentry>
<onexit>
<cancel sendid="timeoutTimer"/>
</onexit>
<transition event="timeout" target="expired"/>
</state>
Troubleshooting
Common Issues
"Unknown event" warning
Events must be declared or use EVT_UNKNOWN for dynamic events.
Solution: Use generated EVT_* constants for O(1) dispatch.
Delayed events not firing
Java: Ensure executor is started and running
JavaScript: Check setTimeout is available
C (bare-metal): Call tick() in main loop
Invoke child not found
Use --bundle-auto to bundle external children at compile time.
Without bundling, external src requires runtime SCXML loading.
Getting Support
For help with vscxml, consult the documentation:
- Visual Editor Guide
- Simulator Guide
- Generator Guide
- MCP Setup Guide — AI integration troubleshooting
- W3C SCXML Specification
Quick Reference
SCXML Structure
<?xml version="1.0" encoding="UTF-8"?>
<scxml xmlns="http://www.w3.org/2005/07/scxml"
version="1.0"
datamodel="ecmascript"
initial="start">
<datamodel>
<data id="count" expr="0"/>
</datamodel>
<state id="start">
<onentry>
<log label="info" expr="'Starting...'"/>
</onentry>
<transition event="go" target="running"/>
</state>
<state id="running">
<transition event="stop" target="done"/>
</state>
<final id="done"/>
</scxml>
Generated API (All Targets)
The recommended pattern across all targets is to drive the machine through
its executor: it serializes events from multiple threads, processes
delayed <send> actions automatically, and matches the way generated code
is wired internally. The Machine itself still exposes send(...) for the
simplest cases (no concurrent threads, no delayed events), but examples in
this guide always go through an executor.
| Operation | Java | JavaScript | C# | C | Python | Go |
|---|---|---|---|---|---|---|
| Create machine | new Machine() |
new Machine() |
new Machine() |
Machine_init(&sm) |
Machine() |
NewMachine() |
| Create executor | new ContinuousStateMachineExecutor(sm) |
new ContinuousExecutor(sm) |
new ContinuousExecutor(sm) |
scxml_cexec_init(&exec, &sm, ...) |
ContinuousExecutor(sm) |
scxmlgen.NewContinuousExecutor(sm) |
| Start | executor.start() |
executor.start() |
executor.Start() |
scxml_cexec_start(&exec) |
executor.start() |
executor.Start() |
| Send event | executor.send("evt") / executor.send(EVT) |
executor.send('evt') |
executor.Send("evt") |
scxml_cexec_send(&exec, EVT, NULL) |
executor.send("evt") |
executor.Send("evt") |
| Check state | machine.isInState("s") |
machine.isInState('s') |
machine.IsInState("s") |
Machine_is_in(&sm, S) |
machine.is_in_state("s") |
machine.IsInState("s") |
| Pump delayed | executor.pumpEvents() |
executor.pumpEvents() |
executor.PumpEvents() |
scxml_cexec_tick(&exec) (bare-metal) |
executor.pump_events() |
executor.Pump() (via wakeup) |
| Stop / dispose | executor.close() |
executor.stop() |
executor.Dispose() |
scxml_cexec_stop(&exec) |
executor.stop() |
executor.Stop() |
The desktop/server executors (Java, JavaScript, C#, Python, Go) start the machine for you when you call
executor.start()— do not also callmachine.start()directly, that would double-enter the initial state. The CScxmlContinuousExecutorwires the machine viascxml_cexec_initand uses your machine's_startfunction explicitly.
Event Introspection (All Targets)
| Method | Description |
|---|---|
getAllEvents() |
All events the machine can react to (static analysis) |
getEnabledEvents() |
Events enabled in the current configuration (guard-aware) |
getEventsForState(id) |
Events a specific state reacts to (static, includes ancestors) |
getEnabledEventsForState(id) |
Events enabled for a specific active state (guard-aware) |
getEnabledEvents() evaluates guard conditions at query time -- In() predicates compile to O(1) bitset checks, native expressions evaluate directly, and ECMAScript guards use the datamodel engine.
Next Steps
Tool Guides
- Visual Editor — Complete editor documentation
- Simulator — Testing and debugging guide
- Generator — Code generation reference (CLI + desktop app)
- MCP Setup — AI integration with Claude Code and other LLM tools
Target Guides
- Java — JVM integration, executors, GraalVM
- JavaScript — React/Vue, runtime interpreter
- C# — .NET 6+, Unity, Jint ECMAScript
- C — Arduino, memory optimization, MISRA
- Python — dukpy ECMAScript, threading
- Go — Goja ECMAScript, goroutines
- Structured Text — IEC 61131-3, CODESYS, TwinCAT
Tutorials
- Quick Start — Minimal traffic light example
- Traffic Light Tutorial — Interactive tutorial with European-style traffic light
- Arduino Light Switch — Embedded example
- Invoke Feature — Child state machines