machine-lang
v0.3.5
Published
Dynamic state machine prototyping language
Readme
DyGram 🔄
Dynamic state machine prototyping language - Transform thoughts into executable systems
What is DyGram?
DyGram (formerly "Machine", aka "ideo-gram") is a lean, executable DSL for rapid prototyping that evolves from unstructured sketches to complete systems through iterative execution and generative prompting. It bridges the gap between conceptual thinking and structured implementation.
Key Features
- 🚀 Immediately Executable: Start with broad, unstructured concepts that run from day one
- 🛤️ Rails-Based Execution: Single agent rides machine rails with automated + intelligent transitions
- 🔧 Meta-Programming: Agents can construct tools dynamically and improve them iteratively
- 🏗️ Semantic Nesting: Hierarchical namespaces with qualified names and automatic context inheritance
- 📱 Mobile-First: CodeMirror 6-based playground optimized for touch devices
- 🔄 Iterative Evolution: Refine through execution, feedback, and continuous iteration
- 🎯 Lean Core DSL: Minimal, intuitive language capturing domain concepts
- 🧩 Structured Emergence: Watch systems naturally evolve from sketches to implementations
- ⚡ Language Server Support: Full LSP integration with Langium
Quick Start
Installation
npm installDevelopment
# Start development server
npm run dev
# Build for production
npm run bundle
# Run tests
npm testCLI Usage
# Generate machine outputs
npx dygram generate your-file.dygram --format json,html
# Execute a machine
npx dygram execute your-file.dygram
# Execute with specific model
npx dygram execute your-file.dygram --model claude-3-5-sonnet-20241022
# Execute with verbose logging
npx dygram execute your-file.dygram --verbose
# Batch process multiple files
npx dygram batch "examples/**/*.dygram" --format jsonModel Selection: Models can be specified via (in priority order):
- Task-level (highest): Individual tasks can specify
modelIdattribute - CLI parameter:
--model claude-3-5-sonnet-20241022 - Machine-level: Define a
confignode withmodelIdattribute - Environment variable:
export ANTHROPIC_MODEL_ID=claude-3-5-haiku-20241022 - Default (lowest):
claude-3-5-haiku-20241022
Example:
config {
modelId: "claude-3-5-haiku-20241022"; // Machine default
};
Task simple {
prompt: "Quick task..."; // Uses machine default (haiku)
};
Task complex {
modelId: "claude-3-5-sonnet-20241022"; // Task override
prompt: "Complex reasoning...";
};See Model Configuration Examples and LLM Client Usage for more details.
Playground Options
We provide two playground environments:
1. Mobile Playground (Recommended for Touch Devices)
URL: /playground-mobile.html
Built with CodeMirror 6 for superior mobile experience:
- ✅ Native touch selection and editing
- ✅ Optimized for small screens
- ✅ Responsive layout (portrait/landscape)
- ✅ Touch-friendly controls
- ✅ Web Share API support
2. Monaco Playground (Desktop-Optimized)
URL: /playground.html
Traditional Monaco editor with full Langium LSP:
- ✅ Advanced IntelliSense
- ✅ Real-time validation
- ✅ Rich language features
- ⚠️ Less optimal on mobile devices
Rails-Based Architecture ⚡
DyGram features a unique execution model where your machine definition acts as "rails" that guide a Claude agent:
- 🛤️ Automated Transitions: Deterministic paths execute instantly without LLM calls
- 🤖 Agent Decisions: Complex branching requires intelligent agent reasoning
- 🔧 Meta-Programming: Agents can construct tools and modify the machine dynamically
- 📊 Phase-Specific Context: Agents receive only relevant data at each node
Example:
machine "Smart Pipeline"
State idle;
Task analyze {
meta: true;
prompt: "Analyze data. Construct tools if needed.";
};
// Automatic transition (no agent)
idle -@auto-> analyze;
// Agent-controlled (complex decision)
analyze -> success, retry, abort;Learn more: Rails-Based Architecture Documentation | Examples
Language Syntax
Basic Structure
machine "My System"
// Define nodes
state start;
state process;
state end;
// Define connections
start -> process -> end;Typed Concepts
machine "Task System"
Concept task "User Story" {
description<string>: "Implement feature";
priority<Integer>: 8;
tags: ["backend", "api"];
};
Concept implementation {
status: "In Progress";
owner: "Engineering";
};
task -drives-> implementation;Generative Tasks
machine "AI Pipeline"
Input query {
text<string>: "Analyze sentiment";
};
Task analyze {
prompt: "Given {{ query.text }}, provide analysis";
};
Result output {
sentiment: "TBD";
};
query -> analyze -> output;Semantic Nesting & Namespaces
DyGram supports semantic nesting with qualified names and automatic context inheritance:
machine "Data Pipeline"
// Global configuration
context globalConfig {
apiUrl: "https://api.example.com";
timeout: 5000;
}
// Nested pipeline structure
task DataPipeline {
context pipelineState {
recordsProcessed: 0;
}
task ValidationPhase {
task validate {
prompt: "Validate data";
// Automatically inherits read access to globalConfig and pipelineState
}
}
task ProcessingPhase {
task transform {
prompt: "Transform data";
// Also inherits read access to parent contexts
}
}
}
// Reference nested nodes using qualified names
start -> DataPipeline.ValidationPhase.validate;
DataPipeline.ValidationPhase.validate -> DataPipeline.ProcessingPhase.transform;
// Parent pipeline has explicit access to config
DataPipeline -reads-> globalConfig;
DataPipeline -writes-> DataPipeline.pipelineState;
// Children automatically inherit read-only access (no explicit edges needed)Key Features:
- Qualified Names (Phase 1): Reference nested nodes using dot notation (e.g.,
Parent.Child.GrandChild) - Context Inheritance (Phase 1): Child nodes automatically inherit read-only access to parent contexts
- State Modules (Phase 2): State nodes with children act as workflow modules with automatic entry/exit routing
- Reduced Boilerplate: No need for repetitive context edges or explicit module wiring
- Intuitive Scoping: Hierarchical structure reflects natural context and workflow relationships
Example - State Module:
state DataPipeline {
state validate -> process -> store;
}
// Transitioning to DataPipeline automatically enters at 'validate'
start -> DataPipeline;
// Terminal nodes inherit module-level exits
DataPipeline -> complete; // 'store' (terminal) transitions to 'complete'See Nesting Examples for more details.
Project Structure
.
├── src/
│ ├── language/ # Langium language definition
│ ├── cli/ # Command-line interface
│ ├── extension/ # VS Code extension
│ ├── web/ # Web utilities
│ └── codemirror-setup.ts # CodeMirror 6 integration
├── static/
│ └── styles/ # CSS stylesheets
├── docs/ # Documentation
├── test/ # Test files
├── index.html # Landing page (root for GitHub Pages)
├── playground.html # Monaco playground
├── playground-mobile.html # CodeMirror mobile playground
└── vite.config.ts # Build configurationDevelopment Workflow
1. Language Changes
When modifying the grammar:
# Regenerate language artifacts
npm run langium:generate
# Watch for changes
npm run langium:watch2. Building
# Full build (Langium + TypeScript + esbuild)
npm run build
# Build for web
npm run build:web
# Bundle with Vite
npm run bundle3. Testing
# Run all tests
npm test
# Watch mode
npm test -- --watchTechnology Stack
- Language Framework: Langium - DSL toolkit
- Desktop Editor: Monaco Editor - VS Code's editor
- Mobile Editor: CodeMirror 6 - Mobile-optimized editor
- Build Tool: Vite - Fast build tool
- Visualization: Mermaid - Diagram generation
- Runtime: Node.js 18+
Why Two Playgrounds?
Monaco Editor provides excellent desktop experience with full LSP integration but struggles on mobile devices due to:
- Complex touch interactions
- Heavy resource usage
- Non-native selection behavior
CodeMirror 6 solves these issues with:
- Native mobile selection/editing
- Lightweight architecture
- Touch-optimized UI
- Better performance on mobile
Choose based on your device - both support the same DyGram language!
GitHub Pages Deployment
The site is configured for GitHub Pages with the landing page at the root:
https://yourusername.github.io/machine/ → Landing page
https://yourusername.github.io/machine/playground-mobile.html → Mobile playground
https://yourusername.github.io/machine/playground.html → Monaco playgroundDeploy via:
npm run bundle
# Push dist/ folder or configure GitHub ActionsVS Code Extension
Install the DyGram extension for:
- Syntax highlighting
- Code completion
- Real-time validation
- Mermaid diagram preview
Contributing
- Fork the repository
- Create a feature branch
- Make your changes
- Run tests:
npm test - Submit a pull request
License
See LICENSE.md
Documentation
Comprehensive documentation is available in the docs/ directory:
- Quick Start - Get started quickly
- Language Overview - Introduction to DyGram
- Syntax Guide - Complete syntax reference
- Advanced Features - Advanced language features
- Examples Index - Comprehensive example catalog
- API Reference - API documentation
See the documentation index for the complete list.
Links
- Live Demo: http://www.christopherdebeer.com/machine/
- Documentation: docs/
- GitHub Repository: https://github.com/christopherdebeer/machine
Note: Monaco editor is powerful for desktop but not ideal for mobile. We've added CodeMirror 6 for a superior mobile experience while maintaining the Monaco version for desktop users who prefer its advanced features.
Powered by Langium, Monaco, CodeMirror, and Mermaid
