Schema Reference
Complete specification for simulation JSON files.
Simulation Root
A simulation is a single JSON object with these top-level fields:
| Field | Type | Description | |
|---|---|---|---|
| id | string | required | Unique identifier, e.g. "my-demo-1" |
| title | string | required | Display name shown in the simulation picker |
| description | string | required | Short description (can be empty string) |
| productType | string | required | "claude-code", "claude-code-gui", "claude-chat", "claude-cowork", or "chatgpt" |
| createdAt | string | required | ISO 8601 timestamp |
| updatedAt | string | required | ISO 8601 timestamp |
| metadata | object | required | Contains exactly one config matching productType |
| events | array | required | Ordered list of event objects |
Metadata Configs
The metadata object must contain exactly one config field matching the productType:
| productType | metadata field |
|---|---|
| "claude-code" | metadata.codeConfig |
| "claude-code-gui" | metadata.guiConfig (plus metadata.codeConfig for the embedded terminal) |
| "claude-chat" | metadata.chatConfig |
| "claude-cowork" | metadata.coworkConfig |
| "chatgpt" | metadata.gptConfig |
CodeConfig
| Field | Type | Example | |
|---|---|---|---|
| modelName | string | required | "claude-opus-4-6" |
| gitBranch | string | required | "main" |
| workingDirectory | string | required | "/Users/dev/myproject" |
| initialCost | string | required | "$0.00" |
| initialContext | number | required | 0–100, e.g. 3 |
ChatConfig
| Field | Type | Description | |
|---|---|---|---|
| modelName | string | required | e.g. "Claude Opus 4" |
| theme | string | required | "light" or "dark" |
| conversationTitle | string | required | Title shown in the header |
| sidebarConversations | array | required | List of SidebarConversation objects |
| projects | array | required | List of SidebarProject objects |
SidebarConversation:
| Field | Type | Description | |
|---|---|---|---|
| id | string | required | Unique identifier |
| title | string | required | Conversation title |
| timestamp | string | required | e.g. "Just now", "2h ago" |
| isActive | boolean | required | true for the current conversation |
SidebarProject:
| Field | Type | Description | |
|---|---|---|---|
| id | string | required | Unique identifier |
| name | string | required | Project name |
| conversationCount | number | required | Number of conversations |
CoworkConfig
| Field | Type | Example | |
|---|---|---|---|
| taskTitle | string | required | Title of the task |
| folderPath | string | required | "/Users/dev/project" |
| suggestions | array | required | List of suggestion strings |
Event Base Fields
Every event has these base fields:
| Field | Type | Description | |
|---|---|---|---|
| id | string | required | Unique within the simulation |
| type | string | required | Event type name |
| delayMs | number | required | Milliseconds to wait before starting |
| durationMs | number | optional | Override calculated duration |
user-message
All product types · Default duration: typingEffect ? (content.length / 30) * 1000 : 0
| Field | Type | Description | |
|---|---|---|---|
| content | string | required | The message text |
| typingEffect | boolean | required | true = animate typing |
assistant-message
All product types · Default duration: (content.length / cps) * 1000 — slow=8, normal=20, fast=45 cps
| Field | Type | Description | |
|---|---|---|---|
| content | string | required | Markdown-supported message text |
| streamingSpeed | string | required | "slow", "normal", or "fast" |
thinking
All product types · Default duration: 3500ms
| Field | Type | Description | |
|---|---|---|---|
| label | string | optional | Text shown during thinking, e.g. "Analyzing codebase..." |
tool-call
Code, Cowork · Default duration: 600ms
| Field | Type | Description | |
|---|---|---|---|
| toolName | string | required | e.g. "Read", "Edit", "Bash" |
| toolInput | object | required | Parameter object (any shape) |
| description | string | optional | Human-readable label in UI |
| expandedByDefault | boolean | required | true = card starts open |
tool-result
Code, Cowork · Default duration: 400ms
| Field | Type | Description | |
|---|---|---|---|
| toolCallId | string | required | Must match id of a preceding tool-call |
| output | string | required | Result text |
| isError | boolean | required | true if error result |
| isCollapsed | boolean | required | true = collapsed initially |
permission-prompt
Code only · Default duration: 0 (waits for response)
| Field | Type | Description | |
|---|---|---|---|
| toolName | string | required | Tool requesting permission |
| description | string | required | What permission is requested |
| command | string | optional | Actual command/action |
permission-response
Code only · Default duration: 200ms
| Field | Type | Description | |
|---|---|---|---|
| promptId | string | required | Must match id of a preceding permission-prompt |
| response | string | required | "allow", "deny", or "allow-always" |
artifact
Chat, Cowork · Default duration: 2500ms
| Field | Type | Description | |
|---|---|---|---|
| artifactType | string | required | "code", "html", "react", "markdown", "svg", "word", "pdf" |
| title | string | required | Title on the artifact card |
| content | string | required | Full source/HTML/markdown content |
| language | string | optional | Syntax hint for "code" type |
Routing: "word" / "pdf" open in document viewer; all others open in simulated Chrome.
status-bar-update
Code only · Default duration: 0 (instant)
| Field | Type | Description | |
|---|---|---|---|
| updates | object | required | Partial update (see below) |
updates object fields (all optional):
| Field | Type | Description |
|---|---|---|
| cost | string | e.g. "$0.03" |
| contextPercent | number | 0–100 |
| modelName | string | e.g. "claude-opus-4-6" |
| gitBranch | string | e.g. "feature/auth" |
cowork-progress
Cowork only · Default duration: 500ms
| Field | Type | Description | |
|---|---|---|---|
| stepIndex | number | required | 0-based step number |
| stepLabel | string | required | e.g. "Scanning project" |
| status | string | required | "pending", "running", "complete", "error" |
| detail | string | optional | Additional status text |
Events with the same stepIndex update the same step in the sidebar.
cowork-notification
Cowork only · Default duration: 300ms
| Field | Type | Description | |
|---|---|---|---|
| notificationType | string | required | "finished", "needs-input", "error" |
| message | string | required | Notification text |
pause
All product types · Default duration: 2000ms
No additional fields beyond base. Use durationMs to control the pause length. Creates a deliberate break between conversation turns.
Timing Rules
The effective delay before an event starts:
MIN_DELAY values
| Event type | MIN_DELAY (ms) |
|---|---|
| thinking | 800 |
| assistant-message | 600 |
| tool-call | 500 |
| tool-result | 400 |
| artifact | 1500 |
| cowork-progress | 400 |
| cowork-notification | 600 |
| all others | 0 |
Recommended timing patterns
| Pattern | delayMs | Duration / speed |
|---|---|---|
| First user message | 0 | typingEffect: true or false |
| Thinking after user message | 300–500 | 800–1500 |
| Assistant after thinking | 200–300 | streamingSpeed: "normal" |
| Tool call after assistant | 200–400 | (default 600) |
| Tool result after tool call | 100 | (default 400) |
| Artifact after assistant | 400–600 | (default 2500) |
| Status bar update | 0 | (instant) |
| Gap between turns | 500–1500 | use pause or delayMs |
Conventions
Page breaks in documents
For "word" and "pdf" artifacts, split content into pages with ---PAGE--- on its own line.
Event cross-references
tool-result.toolCallId must match a preceding tool-call.id. permission-response.promptId must match a preceding permission-prompt.id.
Event IDs
Must be unique within the simulation. Convention: "e1", "msg-1", "tool-read-1".
Markdown in content
assistant-message supports markdown (bold, italic, lists, code blocks). Word/PDF artifacts support GFM tables.