Lab Structure
A lab is defined by a directory containing:- lab.yaml - Lab manifest with configuration
- instructions.md - Markdown instructions shown to the user
- scaffold/ - Initial workspace files (copied on first run)
- overlay/ - Files applied on every lab start (overrides user changes)
- solution/ (optional) - Reference solution for comparison
- tests/ - Automated test suite
Lab Manifest (lab.yaml)
lab.yaml
Display name shown in the lab header
fresh: Standalone workspace (default)continue: Shares workspace from previous lab
Command to run automated tests (e.g.,
npm test, pytest, cargo test)Files to open in the editor when the lab starts
Shell commands to run during first-time provisioning (e.g.,
npm install, pip install -r requirements.txt)Docker services to start. Can use preset names (
postgres, redis, mongodb) or custom service definitions.Lifecycle Phases
Labs transition through a declarative lifecycle managed by React Query (src/lab/use-lifecycle.ts):Provisioning
- Check for container runtime (if services defined)
- Scaffold workspace from
scaffold/directory (first run only) - Apply
overlay/files (every run) - Generate
docker-compose.ymlfrom service definitions - Run
docker compose upwith health checks - Execute setup commands
- Open initial files
- Spawn default terminal
Workspace Modes
Fresh Workspace
Each lab gets an isolated directory. User progress persists across sessions but is independent of other labs. Use case: Standalone exercises, self-contained projectsContinue Workspace
Shares the workspace from the previous lab in the sequence. User builds incrementally on prior work. Use case: Multi-part tutorials where Lab 2 extends Lab 1’s codeFile System
The lab environment provides full file tree access with:- Monaco editor with language servers (TypeScript, Python, Rust, Go, etc.)
- File tree with create/rename/delete operations
- Git integration with diff markers and status badges
- Split editor for side-by-side editing (including solution comparison)
- Auto-save with dirty state tracking
File Operations (src/lab/use-file-ops.ts)
Terminal Integration
Labs provide full PTY (pseudo-terminal) access viaxterm.js with:
- Multiple terminal tabs
- Shell persistence across UI sessions
- Custom spawn options (shell, args, working directory)
- Terminal rename and reordering
Spawning Terminals
Automated Testing
Labs run test commands and parse output to provide structured feedback.TAP Format Parser
The test runner (src/lab/use-test-runner.ts) parses TAP (Test Anything Protocol) output:Test States
Idle
No test run initiated
Running
Test command executing, streaming output
Passed
All assertions passed
Failed
One or more assertions failed
Error
Test command crashed or exited non-zero without TAP
Custom Test Commands
Labs support any test runner that produces output:- JavaScript:
npm test,jest,vitest - Python:
pytest,unittest - Rust:
cargo test - Go:
go test ./...
Docker Services
Labs can define containerized services that start automatically.Preset Services (src/lab/presets.ts)
Custom Services
Container Lifecycle
Service containers are managed bydocker-compose.yml generated at runtime:
- Detect runtime (Docker or Podman)
- Generate compose file (src/lab/compose.ts)
- Run
compose upwith streaming event logs - Poll health checks until all services healthy
- Update service status badges in UI
Container Actions
The Services panel provides:- Start/Stop/Restart individual containers
- View Logs with streaming output
- Exec into container (spawns terminal with
/bin/sh) - Container status (starting, healthy, failed)
Language Server Protocol (LSP)
Labs integrate language servers for IntelliSense, go-to-definition, and diagnostics.Supported Languages (src/lab/lsp/server-registry.ts)
- TypeScript/JavaScript:
typescript-language-server - Python:
pyright - Rust:
rust-analyzer - Go:
gopls
Document Sync
The LSP client (src/lab/lsp/document-sync.ts) maintains:textDocument/didOpenon file opentextDocument/didChangeon editor changes (debounced)textDocument/didSaveon savetextDocument/didCloseon file close
Vim Mode
Labs support Vim keybindings via Monaco’s Vim mode adapter (src/lab/vim-status-store.ts). Toggle withCtrl+Shift+V or through settings.
Solution Comparison
When asolution/ directory exists, users can open solution files side-by-side with their code:
Hotkeys
Labs provide extensive keyboard shortcuts (src/lab/hotkeys/registry.ts):| Shortcut | Action |
|---|---|
Ctrl+S | Save active file |
Ctrl+P | Open command palette |
Ctrl+Shift+P | Open file picker |
Ctrl+B | Toggle file tree |
Ctrl+J | Toggle terminal |
Ctrl+Shift+T | Run tests |
Ctrl+G | Go to line |
Ctrl+Shift+V | Toggle Vim mode |
Persistence
Lab workspaces persist across sessions using a SQLite database (src-tauri/src/workspace.rs):- First-run detection (scaffold only applied once)
- Workspace path resolution
- User file edits preserved
- Terminal state persists
overlay/ directory is the only mechanism to override user changes.