# API Reference

Complete WebSocket API command reference

## Client Commands

### get_clients

Get list of all managed clients (windows).

    // Request
    {"command": "get_clients"}

    // Response
    {
        "status": "ok",
        "clients": [
            {
                "window": 12345678,
                "title": "Window Title",
                "class": "window-class",
                "workspace": 0,
                "x": 0,
                "y": 32,
                "width": 960,
                "height": 540,
                "focused": true,
                "floating": false,
                "fullscreen": false,
                "maximized": false,
                "minimized": false
            }
        ]
    }

### find_clients

Search for clients by title, class, or workspace.

    // Request - find by title (substring match)
    {"command": "find_clients", "title": "Firefox"}

    // Request - find by class
    {"command": "find_clients", "class": "terminal"}

    // Request - find by workspace
    {"command": "find_clients", "workspace": 2}

    // Request - combine filters
    {"command": "find_clients", "class": "code", "workspace": 0}

    // Response
    {
        "status": "ok",
        "clients": [...]
    }

### get_focused_client

Get the currently focused client.

    // Request
    {"command": "get_focused_client"}

    // Response
    {
        "status": "ok",
        "client": {
            "window": 12345678,
            "title": "...",
            "class": "...",
            ...
        }
    }

### focus_client

Focus a client by window ID. Switches workspace if needed.

    // Request
    {"command": "focus_client", "window": 12345678}

    // Response (returns current status)
    {
        "status": "ok",
        "version": "2.0.0",
        "current_workspace": 0,
        "client_count": 5
    }

### close_client

Close a client gracefully (sends WM_DELETE_WINDOW).

    // Request
    {"command": "close_client", "window": 12345678}

    // Response
    {"status": "ok"}

### kill_client

Force kill a client (XKillClient). Use when close_client fails.

    // Request
    {"command": "kill_client", "window": 12345678}

    // Response
    {"status": "ok"}

### move_client

Move a client to specified position.

    // Request
    {
        "command": "move_client",
        "window": 12345678,
        "x": 100,
        "y": 100
    }

    // Response
    {"status": "ok"}

### resize_client

Resize a client to specified dimensions.

    // Request
    {
        "command": "resize_client",
        "window": 12345678,
        "width": 800,
        "height": 600
    }

    // Response
    {"status": "ok"}

### minimize_client

Minimize a client.

    {"command": "minimize_client", "window": 12345678}

### restore_client

Restore a minimized client.

    {"command": "restore_client", "window": 12345678}

### maximize_client

Maximize or unmaximize a client. Toggles if state not specified.

    // Toggle maximize
    {"command": "maximize_client", "window": 12345678}

    // Set explicit state
    {"command": "maximize_client", "window": 12345678, "state": true}

### fullscreen_client

Set client fullscreen state. Toggles if state not specified.

    // Toggle fullscreen
    {"command": "fullscreen_client", "window": 12345678}

    // Set explicit state
    {"command": "fullscreen_client", "window": 12345678, "state": true}

### float_client

Set client floating state. Toggles if state not specified.

    // Toggle floating
    {"command": "float_client", "window": 12345678}

    // Set explicit state
    {"command": "float_client", "window": 12345678, "state": true}

### raise_client

Raise client to top of stack.

    {"command": "raise_client", "window": 12345678}

### lower_client

Lower client to bottom of stack.

    {"command": "lower_client", "window": 12345678}

## Workspace Commands

### get_workspaces

Get list of all workspaces.

    // Request
    {"command": "get_workspaces"}

    // Response
    {
        "status": "ok",
        "workspaces": [
            {
                "id": 0,
                "name": "1",
                "layout": 0,
                "client_count": 3
            },
            {
                "id": 1,
                "name": "2",
                "layout": 0,
                "client_count": 0
            }
            // ... workspaces 2-8
        ]
    }

### switch_workspace

Switch to specified workspace (0-8). Returns current status.

    // Request
    {"command": "switch_workspace", "workspace": 2}

    // Response
    {
        "status": "ok",
        "version": "2.0.0",
        "current_workspace": 2,
        "client_count": 5
    }

### move_client_to_workspace

Move specific client to workspace.

    {
        "command": "move_client_to_workspace",
        "window": 12345678,
        "workspace": 3
    }

### switch_workspace_next

Switch to the next workspace (wraps around).

    {"command": "switch_workspace_next"}

    // Response
    {
        "status": "ok",
        "workspace": 1,
        "workspace_name": "2"
    }

### switch_workspace_prev

Switch to the previous workspace (wraps around).

    {"command": "switch_workspace_prev"}

## Layout Commands

### set_layout

Set workspace layout mode. Can use string names or numeric values.

    // Set layout by name ("tiling", "floating", or "monocle")
    {"command": "set_layout", "layout": "floating"}

    // Set layout by number (0=tiling, 1=floating, 2=monocle)
    {"command": "set_layout", "layout": 1}

    // Optionally specify workspace (defaults to current)
    {"command": "set_layout", "layout": "monocle", "workspace": 2}

### cycle_layout

Cycle to next layout mode (tiling → floating → monocle → tiling).

    // Cycle current workspace
    {"command": "cycle_layout"}

    // Cycle specific workspace
    {"command": "cycle_layout", "workspace": 3}

### set_master_ratio

Set the master area ratio (0.1-0.9) for tiling layout.

    // Set on current workspace
    {"command": "set_master_ratio", "ratio": 0.6}

    // Set on specific workspace
    {"command": "set_master_ratio", "ratio": 0.55, "workspace": 2}

    // Response
    {
        "status": "ok",
        "workspace": 0,
        "master_ratio": 0.6
    }

### adjust_master_ratio

Adjust the master area ratio by a delta value.

    // Increase master area by 5%
    {"command": "adjust_master_ratio", "delta": 0.05}

    // Decrease master area by 5%
    {"command": "adjust_master_ratio", "delta": -0.05}

### set_master_count

Set the number of windows in the master area (1-10).

    {"command": "set_master_count", "count": 2}

    // Response
    {
        "status": "ok",
        "workspace": 0,
        "master_count": 2
    }

### adjust_master_count

Adjust the master count by a delta value.

    // Add one window to master
    {"command": "adjust_master_count", "delta": 1}

    // Remove one window from master
    {"command": "adjust_master_count", "delta": -1}

### focus_next

Focus the next window in the current workspace.

    {"command": "focus_next"}

    // Response
    {
        "status": "ok",
        "focused_window": 12345678,
        "focused_title": "Firefox"
    }

### focus_prev

Focus the previous window in the current workspace.

    {"command": "focus_prev"}

### focus_master

Focus the first window in the master area.

    {"command": "focus_master"}

### snap_client

Snap a window to screen edge or corner.

    // Snap focused window left
    {"command": "snap_client", "direction": "left"}

    // Snap specific window
    {"command": "snap_client", "window": 12345678, "direction": "right"}

    // Directions: left, right, up, down
    // Snapping is composable: left then up = top-left corner

    // Response
    {
        "status": "ok",
        "window": 12345678,
        "snap": {
            "horizontal": 1,
            "vertical": 0
        }
    }

## Keyboard Commands

### key_press

Simulate key press (key down only). Use `keysym` (X11 keysym name) or `keycode`.

    // By keysym name (X11 keysym names)
    {"command": "key_press", "keysym": "a"}
    {"command": "key_press", "keysym": "Return"}
    {"command": "key_press", "keysym": "Tab"}
    {"command": "key_press", "keysym": "Escape"}
    {"command": "key_press", "keysym": "F1"}
    {"command": "key_press", "keysym": "Control_L"}

    // By keycode (hardware keycode)
    {"command": "key_press", "keycode": 38}

### key_release

Simulate key release (key up only).

    {"command": "key_release", "keysym": "a"}
    {"command": "key_release", "keycode": 38}

### key_tap

Simulate a complete keypress (press + release) with optional modifiers.

    // Simple key tap
    {"command": "key_tap", "keysym": "a"}

    // With modifiers (modifier keysym names)
    {"command": "key_tap", "keysym": "c", "modifiers": ["Control_L"]}
    {"command": "key_tap", "keysym": "t", "modifiers": ["Control_L", "Alt_L"]}
    {"command": "key_tap", "keysym": "s", "modifiers": ["Control_L", "Shift_L"]}

    // Special keys
    {"command": "key_tap", "keysym": "Return"}
    {"command": "key_tap", "keysym": "Tab"}
    {"command": "key_tap", "keysym": "Escape"}
    {"command": "key_tap", "keysym": "F1"}

Common modifier keysyms: `Control_L`, `Control_R`, `Shift_L`, `Shift_R`, `Alt_L`, `Alt_R`, `Super_L`, `Super_R`

### key_type

Type a string of text. Automatically handles shift for uppercase and special characters.

    {"command": "key_type", "text": "Hello, World!"}

## Mouse Commands

### mouse_move

Move mouse to absolute position.

    {"command": "mouse_move", "x": 500, "y": 300}

### mouse_move_relative

Move mouse relative to current position.

    {"command": "mouse_move_relative", "dx": 10, "dy": -5}

### mouse_click

Click mouse button (press + release).

    // Left click at current position
    {"command": "mouse_click", "button": 1}

    // Right click at specific position (moves mouse first)
    {"command": "mouse_click", "button": 3, "x": 100, "y": 200}

Buttons: 1=left, 2=middle, 3=right, 4=scroll up, 5=scroll down

### mouse_press

Press mouse button without releasing (for drag operations).

    {"command": "mouse_press", "button": 1}

### mouse_release

Release mouse button.

    {"command": "mouse_release", "button": 1}

### mouse_scroll

Scroll mouse wheel.

    // Scroll up (amount 1-100, default 1)
    {"command": "mouse_scroll", "direction": "up", "amount": 3}

    // Scroll down
    {"command": "mouse_scroll", "direction": "down", "amount": 3}

### get_mouse_position

Get current mouse position and window under cursor.

    // Request
    {"command": "get_mouse_position"}

    // Response
    {
        "status": "ok",
        "x": 500,
        "y": 300,
        "window_x": 100,
        "window_y": 50,
        "window": 12345678
    }

## Screenshot Commands

### screenshot

Capture screenshot. Returns base64-encoded PNG.

#### Async Mode (Default)

By default, screenshot operations run asynchronously to avoid blocking the API. Set `"async": false` for synchronous behavior.

    // Async (default) - returns when capture completes
    {"command": "screenshot", "mode": "fullscreen"}

    // Synchronous - blocks until complete
    {"command": "screenshot", "mode": "fullscreen", "async": false}

#### Fullscreen Mode

    // Request
    {"command": "screenshot", "mode": "fullscreen"}

    // Response
    {
        "status": "ok",
        "format": "png",
        "encoding": "base64",
        "width": 1920,
        "height": 1080,
        "data": "iVBORw0KGgoAAAANSUhEUg..."
    }

#### Active Window Mode

    {"command": "screenshot", "mode": "active"}

#### Specific Window Mode

    {"command": "screenshot", "mode": "window", "window": 12345678}

#### Area Mode

    {
        "command": "screenshot",
        "mode": "area",
        "x": 100,
        "y": 100,
        "width": 400,
        "height": 300
    }

## OCR Commands

### ocr

Extract text from image using OCR.

#### Async Mode (Default)

OCR operations run asynchronously by default since text extraction can take 1-10 seconds. Set `"async": false` for synchronous behavior.

    // Async (default)
    {"command": "ocr", "image": "...", "language": "eng"}

    // Synchronous
    {"command": "ocr", "image": "...", "language": "eng", "async": false}

#### Request/Response

    // Request
    {
        "command": "ocr",
        "image": "iVBORw0KGgoAAAANSUhEUg...",  // base64 PNG
        "language": "eng"                        // optional, default "eng"
    }

    // Response
    {
        "status": "ok",
        "text": "Extracted text from image...",
        "confidence": 0.95
    }

Common language codes: `eng` (English), `deu` (German), `fra` (French), `spa` (Spanish)

## Notification Commands

### notify

Show a desktop notification.

    // Request
    {
        "command": "notify",
        "summary": "Hello!",
        "body": "This is a notification message",
        "app_name": "My App",
        "timeout": 5000
    }

    // Response
    {
        "status": "ok",
        "notification_id": 1
    }

### close_notification

Close a notification by ID.

    {"command": "close_notification", "id": 1}

### get_notifications

Get list of active notifications.

    {"command": "get_notifications"}

    // Response
    {
        "status": "ok",
        "notifications": [
            {
                "id": 1,
                "app_name": "My App",
                "summary": "Hello!",
                "body": "This is a notification",
                "timeout": 5000,
                "urgency": 1
            }
        ]
    }

## System Tray Commands

### get_battery_state

Get battery status information.

    {"command": "get_battery_state"}

    // Response
    {
        "status": "ok",
        "battery": {
            "present": true,
            "charging": false,
            "percentage": 75,
            "time_remaining": 180
        }
    }

### get_audio_state

Get audio volume and mute status.

    {"command": "get_audio_state"}

    // Response
    {
        "status": "ok",
        "volume": 50,
        "muted": false
    }

### set_audio_volume

Set audio volume (0-100).

    {"command": "set_audio_volume", "volume": 75}

    // Response
    {
        "status": "ok",
        "volume": 75,
        "muted": false
    }

### toggle_audio_mute

Toggle audio mute state.

    {"command": "toggle_audio_mute"}

    // Response
    {
        "status": "ok",
        "muted": true,
        "volume": 75
    }

### get_wifi_state

Get WiFi connection status.

    {"command": "get_wifi_state"}

    // Response
    {
        "status": "ok",
        "enabled": true,
        "connected": true,
        "ssid": "MyNetwork",
        "signal_strength": 80
    }

## Panel Commands

### get_panel_state

Get state of top and bottom panels.

    {"command": "get_panel_state"}

    // Response
    {
        "status": "ok",
        "top_panel": {
            "enabled": true,
            "visible": true,
            "x": 0,
            "y": 0,
            "width": 1920,
            "height": 32
        },
        "bottom_panel": {
            "enabled": true,
            "visible": true,
            "x": 0,
            "y": 1048,
            "width": 1920,
            "height": 32
        }
    }

### show_panel

Show a panel.

    {"command": "show_panel", "panel": "top"}
    {"command": "show_panel", "panel": "bottom"}

### hide_panel

Hide a panel.

    {"command": "hide_panel", "panel": "top"}

### toggle_panel

Toggle panel visibility.

    {"command": "toggle_panel", "panel": "bottom"}

## AI Commands

### ai_is_available

Check if AI features are available (API key configured).

    {"command": "ai_is_available"}

    // Response
    {
        "status": "ok",
        "available": true,
        "model": "google/gemini-2.0-flash-exp:free"
    }

### ai_command

Send a command to the AI assistant. Async by default.

    // Request
    {
        "command": "ai_command",
        "prompt": "What windows are open?",
        "async": true
    }

    // Response (when complete)
    {
        "status": "ok",
        "response": "You have 3 windows open: Firefox, Terminal, and VS Code..."
    }

### exa_is_available

Check if Exa semantic search is available.

    {"command": "exa_is_available"}

    // Response
    {
        "status": "ok",
        "available": true
    }

### exa_search

Perform semantic web search using Exa. Async by default.

    // Request
    {
        "command": "exa_search",
        "query": "how to configure nginx reverse proxy",
        "async": true
    }

    // Response
    {
        "status": "ok",
        "results": [
            {
                "title": "NGINX Reverse Proxy Configuration",
                "url": "https://example.com/nginx-guide",
                "snippet": "Learn how to configure NGINX as a reverse proxy...",
                "score": 0.95
            }
        ]
    }

## News Commands

### get_news

Get news articles from the news ticker.

    {"command": "get_news"}

    // Response
    {
        "status": "ok",
        "current_article": 0,
        "article_count": 10,
        "fetching": false,
        "has_error": false,
        "articles": [
            {
                "title": "Breaking News...",
                "content": "Article content...",
                "link": "https://example.com/news/1",
                "author": "John Doe",
                "sentiment": 0,
                "sentiment_score": 0.5
            }
        ]
    }

### news_next

Navigate to next news article.

    {"command": "news_next"}

    // Response
    {
        "status": "ok",
        "current_article": 1,
        "title": "Next article title..."
    }

### news_prev

Navigate to previous news article.

    {"command": "news_prev"}

### news_open

Open current news article in browser.

    {"command": "news_open"}

    // Response
    {
        "status": "ok",
        "link": "https://example.com/news/1"
    }

## Demo/Tutorial Commands

### start_demo

Start the automated demo mode.

    {"command": "start_demo"}

### stop_demo

Stop the demo mode.

    {"command": "stop_demo"}

### get_demo_state

Get current demo mode state.

    {"command": "get_demo_state"}

    // Response
    {
        "status": "ok",
        "active": true,
        "phase": 2,
        "phase_name": "DEMO_WORKSPACES",
        "step": 3
    }

### start_tutorial

Start the interactive tutorial.

    {"command": "start_tutorial"}

### stop_tutorial

Stop the tutorial.

    {"command": "stop_tutorial"}

### get_tutorial_state

Get current tutorial state.

    {"command": "get_tutorial_state"}

    // Response
    {
        "status": "ok",
        "active": true
    }

## Configuration Commands

### get_config

Get configuration values. Get a specific key or all config.

    // Get specific key
    {"command": "get_config", "key": "terminal"}

    // Response
    {
        "status": "ok",
        "value": "xfce4-terminal"
    }

    // Get all config
    {"command": "get_config"}

    // Response
    {
        "status": "ok",
        "config": {
            "terminal": "xfce4-terminal",
            "launcher": "dmenu_run",
            "focus_mode": "click",
            "border_width": 0,
            "panel_height": 32,
            "gap": 0,
            "ai_enabled": true,
            "fade_speed": 0.5,
            "fade_intensity": 1.0
            ...
        }
    }

### reload_config

Reload configuration from file.

    {"command": "reload_config"}

    // Response
    {
        "status": "ok"
    }

### get_keybindings

Get list of all keyboard shortcuts.

    {"command": "get_keybindings"}

    // Response
    {
        "status": "ok",
        "keybindings": [
            {
                "key": "t",
                "modifiers": "ctrl+alt",
                "description": "Open terminal"
            },
            {
                "key": "F4",
                "modifiers": "alt",
                "description": "Close focused window"
            }
            ...
        ]
    }

## Event Subscription

DWN supports real-time event streaming over WebSocket. Subscribe to events to receive notifications about window actions, workspace changes, input events, and more.

### list_events

Get list of all available event types.

    // Request
    {"command": "list_events"}

    // Response
    {
        "status": "ok",
        "events": [
            "window_created",
            "window_destroyed",
            "window_focused",
            "window_unfocused",
            "window_moved",
            "window_resized",
            "window_minimized",
            "window_restored",
            "window_maximized",
            "window_unmaximized",
            "window_fullscreen",
            "window_unfullscreen",
            "window_floating",
            "window_unfloating",
            "window_title_changed",
            "window_raised",
            "window_lowered",
            "workspace_switched",
            "workspace_window_added",
            "workspace_window_removed",
            "workspace_layout_changed",
            "workspace_master_ratio_changed",
            "workspace_master_count_changed",
            "workspace_arranged",
            "layout_changed",
            "key_pressed",
            "key_released",
            "shortcut_triggered",
            "mouse_moved",
            "mouse_button_pressed",
            "mouse_button_released",
            "drag_started",
            "drag_ended",
            "show_desktop_toggled",
            "notification_shown",
            "notification_closed"
        ]
    }

### subscribe

Subscribe to specific events or all events.

    // Subscribe to specific events
    {"command": "subscribe", "events": ["window_focused", "window_created"]}

    // Subscribe to all events
    {"command": "subscribe", "all": true}

    // Response
    {
        "status": "ok",
        "subscribed": ["window_focused", "window_created"]
    }

### unsubscribe

Unsubscribe from specific events or all events.

    // Unsubscribe from specific events
    {"command": "unsubscribe", "events": ["window_focused"]}

    // Unsubscribe from all events
    {"command": "unsubscribe", "all": true}

    // Response
    {"status": "ok"}

### Event Message Format

When subscribed, events are pushed to the client as JSON messages:

    // Window focus event
    {
        "type": "event",
        "event": "window_focused",
        "data": {
            "window": 12345678,
            "title": "Firefox",
            "previous_window": 87654321
        }
    }

    // Window moved event
    {
        "type": "event",
        "event": "window_moved",
        "data": {
            "window": 12345678,
            "old_x": 0,
            "old_y": 32,
            "new_x": 100,
            "new_y": 100
        }
    }

    // Workspace switched event
    {
        "type": "event",
        "event": "workspace_switched",
        "data": {
            "old_workspace": 0,
            "new_workspace": 2
        }
    }

    // Keyboard shortcut triggered
    {
        "type": "event",
        "event": "shortcut_triggered",
        "data": {
            "name": "Return",
            "description": "Open terminal"
        }
    }

    // Notification shown
    {
        "type": "event",
        "event": "notification_shown",
        "data": {
            "id": 1,
            "summary": "New Message",
            "body": "You have a new message"
        }
    }

    // Fade speed changed
    {
        "type": "event",
        "event": "fade_speed_changed",
        "data": {
            "old_speed": 0.5,
            "new_speed": 1.0
        }
    }

    // Fade intensity changed
    {
        "type": "event",
        "event": "fade_intensity_changed",
        "data": {
            "old_intensity": 1.0,
            "new_intensity": 0.8
        }
    }

### Event Types Reference

Event | Description | Data Fields
--- | --- | ---
`window_created` | New window managed | window, title, class, workspace
`window_destroyed` | Window closed | window, title, workspace
`window_focused` | Window received focus | window, title, previous_window
`window_unfocused` | Window lost focus | window, title
`window_moved` | Window position changed | window, old_x, old_y, new_x, new_y
`window_resized` | Window size changed | window, old_width, old_height, new_width, new_height
`window_minimized` | Window minimized | window
`window_restored` | Window restored from minimized | window
`window_maximized` | Window maximized/unmaximized | window, maximized
`window_fullscreen` | Fullscreen toggled | window, fullscreen
`window_floating` | Floating mode toggled | window, floating
`window_title_changed` | Window title updated | window, old_title, new_title
`workspace_switched` | Active workspace changed | old_workspace, new_workspace
`workspace_layout_changed` | Workspace layout changed | workspace, old_layout, new_layout
`key_pressed` | Key pressed | keycode, keysym, modifiers
`shortcut_triggered` | Keyboard shortcut executed | name, description
`mouse_button_pressed` | Mouse button pressed | button, x, y
`drag_started` | Window drag/resize started | window, is_resize
`drag_ended` | Window drag/resize ended | window, is_resize
`show_desktop_toggled` | Show desktop mode toggled | shown
`notification_shown` | Notification displayed | id, summary, body
`notification_closed` | Notification closed | id
`fade_speed_changed` | Fade animation speed changed | old_speed, new_speed
`fade_intensity_changed` | Fade glow intensity changed | old_intensity, new_intensity
`window_snapped` | Window snapped to position | window, horizontal, vertical
`audio_volume_changed` | System audio volume changed | old_volume, new_volume
`audio_mute_toggled` | System audio mute toggled | muted
`panel_visibility_changed` | Panel shown or hidden | panel, visible
`config_reloaded` | Configuration reloaded | (none)
`ai_response_received` | AI command completed | prompt, response, success
`exa_search_completed` | Exa search completed | query, result_count, success
`news_article_changed` | News ticker article changed | old_index, new_index, title
`demo_started` | Demo mode started | (none)
`demo_stopped` | Demo mode stopped | (none)
`demo_phase_changed` | Demo phase changed | phase, phase_name
`tutorial_started` | Tutorial mode started | (none)
`tutorial_stopped` | Tutorial mode stopped | (none)

## System Commands

### get_status

Get DWN status information.

    // Request
    {"command": "get_status"}

    // Response
    {
        "status": "ok",
        "version": "2.0.0",
        "current_workspace": 0,
        "client_count": 5
    }

### get_screen_info

Get screen and monitor information.

    // Request
    {"command": "get_screen_info"}

    // Response
    {
        "status": "ok",
        "screen_width": 1920,
        "screen_height": 1080,
        "screen": 0,
        "monitor_count": 1,
        "monitors": [
            {
                "index": 0,
                "x": 0,
                "y": 0,
                "width": 1920,
                "height": 1080,
                "primary": true
            }
        ],
        "usable_area": {
            "x": 0,
            "y": 32,
            "width": 1920,
            "height": 1048
        }
    }

### run_command

Spawn a process asynchronously.

    // Request
    {"command": "run_command", "exec": "firefox"}

    // Response
    {"status": "launched"}

### show_desktop

Toggle show desktop mode. Optionally set explicit state.

    // Toggle
    {"command": "show_desktop"}

    // Set explicit state
    {"command": "show_desktop", "state": true}

    // Response
    {
        "status": "ok",
        "desktop_shown": true
    }

### get_fade_settings

Get current fade effect settings (speed and intensity).

    // Request
    {"command": "get_fade_settings"}

    // Response
    {
        "status": "ok",
        "fade_speed": 0.5,
        "fade_intensity": 1.0
    }

### set_fade_speed

Set fade animation speed (0.1 - 3.0, where 1.0 is normal speed).

    // Request
    {"command": "set_fade_speed", "speed": 1.5}

    // Response
    {
        "status": "ok",
        "fade_speed": 1.5
    }

### set_fade_intensity

Set fade glow intensity (0.0 - 1.0, where 1.0 is full intensity).

    // Request
    {"command": "set_fade_intensity", "intensity": 0.8}

    // Response
    {
        "status": "ok",
        "fade_intensity": 0.8
    }

## Error Responses

All commands may return errors:

    {
        "status": "error",
        "message": "Window not found"
    }

    {
        "status": "error",
        "message": "Invalid parameter: workspace must be 0-8"
    }

    {
        "status": "error",
        "message": "Unknown command: invalid_command"
    }