openapi: 3.1.0 info: title: Kernel Images API version: 0.1.0 paths: /recording/start: post: summary: Start a screen recording. Only one recording per ID can be registered at a time. operationId: startRecording requestBody: required: false content: application/json: schema: $ref: "#/components/schemas/StartRecordingRequest" responses: "201": description: Recording started "400": $ref: "#/components/responses/BadRequestError" "409": description: A recording is already in progress $ref: "#/components/responses/ConflictError" "500": $ref: "#/components/responses/InternalError" /process/exec: post: summary: Execute a command synchronously operationId: processExec requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/ProcessExecRequest" responses: "200": description: Execution result content: application/json: schema: $ref: "#/components/schemas/ProcessExecResult" "400": $ref: "#/components/responses/BadRequestError" "500": $ref: "#/components/responses/InternalError" /process/spawn: post: summary: Execute a command asynchronously operationId: processSpawn requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/ProcessSpawnRequest" responses: "200": description: Spawned content: application/json: schema: $ref: "#/components/schemas/ProcessSpawnResult" "400": $ref: "#/components/responses/BadRequestError" "500": $ref: "#/components/responses/InternalError" /process/{process_id}/status: get: summary: Get process status operationId: processStatus parameters: - name: process_id in: path required: true schema: type: string format: uuid responses: "200": description: Status content: application/json: schema: $ref: "#/components/schemas/ProcessStatus" "400": $ref: "#/components/responses/BadRequestError" "404": $ref: "#/components/responses/NotFoundError" "500": $ref: "#/components/responses/InternalError" /process/{process_id}/stdout/stream: get: summary: Stream process stdout over SSE operationId: processStdoutStream parameters: - name: process_id in: path required: true schema: type: string format: uuid responses: "200": description: SSE stream of process output and lifecycle events headers: X-SSE-Content-Type: description: Media type of SSE data events (application/json) schema: type: string const: application/json content: text/event-stream: schema: $ref: "#/components/schemas/ProcessStreamEvent" "400": $ref: "#/components/responses/BadRequestError" "404": $ref: "#/components/responses/NotFoundError" "500": $ref: "#/components/responses/InternalError" /process/{process_id}/stdin: post: summary: Write to process stdin operationId: processStdin parameters: - name: process_id in: path required: true schema: type: string format: uuid requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/ProcessStdinRequest" responses: "200": description: Bytes written content: application/json: schema: $ref: "#/components/schemas/ProcessStdinResult" "400": $ref: "#/components/responses/BadRequestError" "404": $ref: "#/components/responses/NotFoundError" "500": $ref: "#/components/responses/InternalError" /process/{process_id}/kill: post: summary: Send signal to process operationId: processKill parameters: - name: process_id in: path required: true schema: type: string format: uuid requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/ProcessKillRequest" responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/OkResponse" "400": $ref: "#/components/responses/BadRequestError" "404": $ref: "#/components/responses/NotFoundError" "500": $ref: "#/components/responses/InternalError" /process/{process_id}/resize: post: summary: Resize a PTY-backed process operationId: processResize parameters: - name: process_id in: path required: true schema: type: string format: uuid requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/ProcessResizeRequest" responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/OkResponse" "400": $ref: "#/components/responses/BadRequestError" "404": $ref: "#/components/responses/NotFoundError" "500": $ref: "#/components/responses/InternalError" /recording/stop: post: summary: Stop the recording operationId: stopRecording requestBody: required: false content: application/json: schema: $ref: "#/components/schemas/StopRecordingRequest" responses: "200": description: Recording stopped "400": $ref: "#/components/responses/BadRequestError" "500": $ref: "#/components/responses/InternalError" /recording/download: get: summary: Download the most recently recorded video file parameters: - name: id in: query description: Identifier of the recording session to download, as passed to /recording/start. When omitted, the default recording session is downloaded. schema: type: string pattern: "^[a-zA-Z0-9-]+$" operationId: downloadRecording responses: "200": description: Recording file headers: # Note: using a `format: date-time` here doesn't work as intended as the generated code # calls a `fmt.Sprint` on the value when setting the header. time.String is a # non-standard format that most parses will barf on, making everyone's life harder, so # we're skipping the `format` in favor of an explicit description. X-Recording-Started-At: description: Timestamp of when the recording started. Guaranteed to be RFC3339. schema: type: string X-Recording-Finished-At: description: Timestamp of when the recording finished. Guaranteed to be RFC3339. schema: type: string content: video/mp4: schema: type: string format: binary "202": description: Recording is still in progress, please try again later headers: Retry-After: description: Suggested wait time in seconds before retrying schema: type: integer minimum: 1 "400": $ref: "#/components/responses/BadRequestError" "404": $ref: "#/components/responses/NotFoundError" "500": $ref: "#/components/responses/InternalError" /recording/list: get: summary: List all recorders operationId: listRecorders responses: "200": description: List of recorders content: application/json: schema: type: array items: $ref: "#/components/schemas/RecorderInfo" "500": $ref: "#/components/responses/InternalError" /recording/delete: post: summary: Delete a previously recorded video file operationId: deleteRecording requestBody: required: false content: application/json: schema: $ref: "#/components/schemas/DeleteRecordingRequest" responses: "200": description: Recording deleted "400": $ref: "#/components/responses/BadRequestError" "404": $ref: "#/components/responses/NotFoundError" "409": $ref: "#/components/responses/ConflictError" "500": $ref: "#/components/responses/InternalError" /recording/mark: post: summary: Add a named marker to an in-progress recording description: >- Records a named point in time during an active recording. At finalize the markers are injected into the output MP4 as chapter markers. operationId: markRecording requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/MarkRecordingRequest" responses: "201": description: Marker recorded content: application/json: schema: $ref: "#/components/schemas/MarkRecordingResult" "400": $ref: "#/components/responses/BadRequestError" "404": description: No recording session exists with the given identifier $ref: "#/components/responses/NotFoundError" "409": description: The recording session exists but is not actively recording $ref: "#/components/responses/ConflictError" "500": $ref: "#/components/responses/InternalError" /computer/click_mouse: post: summary: Simulate a mouse click action on the host computer operationId: clickMouse requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/ClickMouseRequest" responses: "200": description: Mouse action performed "400": $ref: "#/components/responses/BadRequestError" "500": $ref: "#/components/responses/InternalError" /computer/move_mouse: post: summary: Move the mouse cursor to the specified coordinates on the host computer operationId: moveMouse requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/MoveMouseRequest" responses: "200": description: Mouse cursor moved "400": $ref: "#/components/responses/BadRequestError" "500": $ref: "#/components/responses/InternalError" /computer/screenshot: post: summary: Capture a screenshot of the host computer operationId: takeScreenshot requestBody: required: false content: application/json: schema: $ref: "#/components/schemas/ScreenshotRequest" responses: "200": description: Screenshot image content: image/png: schema: type: string format: binary "400": $ref: "#/components/responses/BadRequestError" "500": $ref: "#/components/responses/InternalError" /computer/cursor: post: summary: Hide or show the cursor operationId: setCursor requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/SetCursorRequest" responses: "200": description: Cursor visibility updated successfully content: application/json: schema: $ref: "#/components/schemas/OkResponse" "400": $ref: "#/components/responses/BadRequestError" "500": $ref: "#/components/responses/InternalError" /computer/get_mouse_position: post: summary: Get the current mouse cursor position on the host computer operationId: getMousePosition responses: "200": description: Current mouse position content: application/json: schema: $ref: "#/components/schemas/MousePositionResponse" "500": $ref: "#/components/responses/InternalError" /computer/type: post: summary: Type text on the host computer operationId: typeText requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/TypeTextRequest" responses: "200": description: Text typed successfully "400": $ref: "#/components/responses/BadRequestError" "500": $ref: "#/components/responses/InternalError" /computer/press_key: post: summary: Press one or more keys on the host computer description: | Presses the specified keys for an optional duration. Keys should be key symbols supported by xdotool. For a comprehensive list of key symbols, see the X11 keysym definitions at https://cgit.freedesktop.org/xorg/proto/x11proto/plain/keysymdef.h The server honors millisecond-level durations using fractional sleeps under the hood. operationId: pressKey requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/PressKeyRequest" responses: "200": description: Keys pressed successfully "400": $ref: "#/components/responses/BadRequestError" "500": $ref: "#/components/responses/InternalError" /computer/scroll: post: summary: Scroll the mouse wheel at a position on the host computer description: | Scroll vertically and/or horizontally at the given coordinates, optionally while holding modifier keys. The scroll amounts are in logical ticks (not pixels) and application behavior may vary; tuning may be required. When both horizontal and vertical deltas are provided, the server applies them sequentially (vertical then horizontal) and batches wheel events using `xdotool click --repeat N --delay 0