--- layout: ../layouts/DocLayout.astro title: Architecture toc: true --- # Architecture ## Client-daemon model deskctl uses a client-daemon architecture over Unix sockets. The daemon starts automatically on the first command and keeps the X11 connection alive so repeated calls skip the connection setup overhead. Each command opens a new connection to the daemon, sends a single NDJSON request, reads one NDJSON response, and exits. ## Wire protocol Requests and responses are newline-delimited JSON (NDJSON) over a Unix socket. **Request:** ```json { "id": "r123456", "action": "snapshot", "annotate": true } ``` **Response:** ```json {"success": true, "data": {"screenshot": "/tmp/deskctl-1234567890.png", "windows": [...]}} ``` Error responses include an `error` field: ```json { "success": false, "error": "window not found: @w99" } ``` ## Socket location The daemon socket is resolved in this order: 1. `--socket` flag (highest priority) 2. `$DESKCTL_SOCKET_DIR/{session}.sock` 3. `$XDG_RUNTIME_DIR/deskctl/{session}.sock` 4. `~/.deskctl/{session}.sock` PID files are stored alongside the socket. ## Sessions Multiple isolated daemon instances can run simultaneously using the `--session` flag: ```sh deskctl --session workspace1 snapshot deskctl --session workspace2 snapshot ``` Each session has its own socket, PID file, and window ref map. ## Backend design The core is built around a `DesktopBackend` trait. The current implementation uses `x11rb` for X11 protocol operations and `enigo` for input simulation. The trait-based design means adding Wayland support is a single trait implementation with no changes to the core, CLI, or daemon code. ## X11 integration Window detection uses EWMH properties: | Property | Purpose | | --------------------------- | ------------------------ | | `_NET_CLIENT_LIST_STACKING` | Window stacking order | | `_NET_ACTIVE_WINDOW` | Currently focused window | | `_NET_WM_NAME` | Window title (UTF-8) | | `_NET_WM_STATE_HIDDEN` | Minimized state | | `_NET_CLOSE_WINDOW` | Graceful close | | `WM_CLASS` | Application class/name | Falls back to `XQueryTree` if `_NET_CLIENT_LIST_STACKING` is unavailable.