Echo Format Reference

April 15, 2026 · View on GitHub

gEcho echoes are human-readable JSON files with a .echo.json extension. They describe a sequence of VS Code interactions that can be replayed deterministically.

File Structure

{
  "version": "1.0",
  "metadata": {
    "name": "My Demo",
    "description": "Optional description of the demo",
    "windowSize": { "width": 1920, "height": 1080 },
    "created": "2026-04-08T00:00:00.000Z",
    "version": "1.0.0"
  },
  "steps": [
    // Array of step objects
  ]
}

Top-Level Fields

FieldTypeRequiredDescription
versionstringSchema version. Must be "1.0".
metadataobjectDescriptive information about the echo.
stepsarrayOrdered list of steps to execute during replay.

Metadata Fields

FieldTypeRequiredDescription
namestringDisplay name for the echo.
descriptionstringWhat the echo demonstrates.
windowSizeobjectTarget VS Code window dimensions (width and height in pixels).
createdstringISO 8601 timestamp of when the echo was created.
versionstringUser-defined version string (e.g., "1.0.0").

Step Types

Every step object has a type field that determines its behavior. There are 9 step types.


type — Type Text

Types text character-by-character into the active editor, simulating natural keyboard input.

{ "type": "type", "text": "console.log('hello');", "delay": 55 }
FieldTypeRequiredDefaultDescription
type"type"Step type identifier.
textstringText to type character by character.
delaynumber55Per-character delay in milliseconds. Controls typing speed.

Notes:

  • The delay value is adjusted by the gecho.replay.speed setting during replay.
  • Multi-line text is supported — include \n for newlines.
  • During echo recording, rapid consecutive single-character insertions within 300 ms can be coalesced into an existing type step once that step already has a delay, helping preserve your natural typing rhythm.

command — Execute a VS Code Command

Executes any VS Code command by its identifier.

{ "type": "command", "id": "editor.action.formatDocument" }

With arguments:

{ "type": "command", "id": "workbench.action.openSettings", "args": "gecho" }
FieldTypeRequiredDescription
type"command"Step type identifier.
idstringVS Code command ID (e.g., workbench.action.files.save).
argsanyOptional arguments passed to the command.

Common commands:

Command IDAction
workbench.action.files.newUntitledFileCreate a new untitled file
workbench.action.files.saveSave the active file
editor.action.formatDocumentFormat the document
workbench.action.terminal.toggleTerminalToggle the integrated terminal
workbench.action.showCommandsOpen the Command Palette

Security: Command IDs are validated against an allowlist pattern during replay. Only alphanumeric characters, dots, hyphens, and underscores are permitted.


key — Press a Key or Shortcut

Simulates a keyboard key press or key combination.

{ "type": "key", "key": "Ctrl+Shift+P" }
FieldTypeRequiredDescription
type"key"Step type identifier.
keystringKey or key combination (e.g., escape, Ctrl+Z, Shift+Alt+F).

Recognized key mappings:

KeyVS Code Command
Ctrl+Shift+P / Cmd+Shift+Pworkbench.action.showCommands
Ctrl+P / Cmd+Pworkbench.action.quickOpen
Ctrl+Z / Cmd+Zundo
Ctrl+Shift+Z / Cmd+Shift+Zredo
Tabtab
EnteracceptSelectedSuggestion
EscapecancelSelection

For single printable characters, gEcho types the character directly. Unrecognized multi-key combinations are skipped.


select — Set Text Selection

Sets the text selection in the active editor by specifying anchor and active (cursor) positions.

{ "type": "select", "anchor": [0, 0], "active": [0, 20] }
FieldTypeRequiredDescription
type"select"Step type identifier.
anchor[line, character]Start of selection (zero-based).
active[line, character]End of selection / cursor position (zero-based).

Notes:

  • Positions are zero-based: [0, 0] is the first character of the first line.
  • If anchor equals active, the selection is collapsed (just a cursor position).
  • To select an entire line, use [line, 0] for anchor and [line, lineLength] for active.

wait — Pause Execution

Pauses replay for a specified duration, optionally waiting for VS Code to become idle.

{ "type": "wait", "ms": 2000 }
FieldTypeRequiredDescription
type"wait"Step type identifier.
msnumberDuration to wait in milliseconds.
until"idle"Optional condition to wait for before continuing. Currently the step sleeps for ms when set to "idle".

Notes:

  • The ms value is adjusted by the gecho.replay.speed setting.
  • To account for async operations (e.g., IntelliSense, file loading), use a generous ms value rather than relying on until.
  • A wait step at the end of your echo gives the viewer time to see the final result in the GIF.

openFile — Open a File

Opens a file in the VS Code editor.

{ "type": "openFile", "path": "src/index.ts" }
FieldTypeRequiredDescription
type"openFile"Step type identifier.
pathstringPath to the file, relative to the workspace root.

Notes:

  • Paths are relative to the workspace root by default.
  • The path is sanitized during replay to prevent directory traversal attacks.
  • The file must exist in the workspace for the step to succeed.

paste — Paste Text

Pastes text into the active editor, replacing the current selection (if any).

{ "type": "paste", "text": "const greeting = 'hello world';" }
FieldTypeRequiredDescription
type"paste"Step type identifier.
textstringText to paste into the editor.

Notes:

  • Unlike type, paste inserts all text at once (no character-by-character animation).
  • Replaces the current selection if text is selected.
  • Useful for inserting large blocks of code without a slow typing animation.

scroll — Scroll the Editor

Scrolls the active editor up or down by a specified number of lines.

{ "type": "scroll", "direction": "down", "lines": 10 }
FieldTypeRequiredDescription
type"scroll"Step type identifier.
direction"up" | "down"Scroll direction.
linesintegerNumber of lines to scroll (minimum 1).

focus — Move Focus to a UI Area

Moves keyboard focus to a named VS Code UI area. Use this after command or key steps that shift focus away from the editor (e.g. opening the Command Palette, toggling the terminal).

{ "type": "focus", "target": "editor" }
FieldTypeRequiredDescription
type"focus"Step type identifier.
target"editor" | "terminal" | "panel" | "sidebar"UI area to focus.

Targets:

TargetVS Code action
editorFocus the active editor group — use this to restore text-editor focus so subsequent type/select/paste/scroll steps land in the right place.
terminalFocus the integrated terminal.
panelFocus the bottom panel (Output, Problems, etc.).
sidebarFocus the primary side bar (Explorer, Search, etc.).

Notes:

  • Insert a { "type": "focus", "target": "editor" } step whenever a prior command or key step may have moved focus away from the editor and you want subsequent keystrokes to target the text pane.
  • The VS Code API does not expose which widget currently holds keyboard focus, so gEcho cannot auto-insert focus steps — authors must add them manually where needed.

JSON Schema

gEcho ships with a JSON Schema at schemas/gecho-v1.schema.json. VS Code automatically validates .echo.json files (current extension) and .gecho.json files (legacy extension, supported for backward compatibility) against this schema, providing IntelliSense, auto-completion, and error highlighting as you edit echoes.

Example Echo

A complete example echo demonstrating all step types is available at echoes/example.echo.json.

{
  "version": "1.0",
  "metadata": {
    "name": "Example Echo",
    "description": "Demonstrates all gEcho step types",
    "created": "2026-04-08T00:00:00.000Z"
  },
  "steps": [
    { "type": "openFile", "path": "src/extension.ts" },
    { "type": "wait", "ms": 500 },
    { "type": "type", "text": "// Hello from gEcho!", "delay": 55 },
    { "type": "command", "id": "workbench.action.files.save" },
    { "type": "focus", "target": "editor" },
    { "type": "select", "anchor": [0, 0], "active": [0, 20] },
    { "type": "key", "key": "escape" },
    { "type": "paste", "text": "// Pasted text" },
    { "type": "scroll", "direction": "down", "lines": 3 },
    { "type": "wait", "ms": 1000, "until": "idle" }
  ]
}

Tips for Authoring Echoes

  • Start with a recording, then clean up the JSON. The echo recorder captures your natural timing, which you can adjust in the JSON.
  • Add wait steps after commands that trigger async operations (IntelliSense, file loading, formatting).
  • Use openFile at the beginning to ensure the correct file is active.
  • End with a wait so the final state is visible in the GIF output.
  • Keep delay values between 30–80 ms for natural-looking typing in GIFs.
  • Use paste for large code blocks to avoid lengthy typing animations.
  • Insert focus steps after any command or key that shifts focus away from the editor (e.g., after workbench.action.terminal.toggleTerminal, add { "type": "focus", "target": "editor" } before the next type or select step).