Skip to content

plugin-wl

Placement runtime (out-of-process over gRPC)
Source github.com/opencharly/charly/candy/plugin-wl
Version 2026.187.1200
Candy plugin-wl

This plugin is not listed in charly/charly.yml’s compiled_plugins:. It is not part of the shipped binary: charly builds and loads it out-of-process over gRPC when a plan references one of its words (the coexist path).

The reserved words this plugin serves:

  • wl — verb class

OUT-OF-TREE charly plugin serving the wl live-container check verb — a standalone Go module (go.mod + main.go) that drives Wayland/sway desktop automation inside a running deployment (input, windows, screenshots, sway IPC, overlay, atspi, clipboard — ~40 methods) over go-plugin gRPC via the charly plugin SDK (github.com/opencharly/sdk). charly’s loader fetches this candy’s repo, go-builds the provider binary on the HOST, and serves it OUT-OF-PROCESS via LocalTransport — so the Wayland/sway driver lives HERE, out of charly’s core check surface. wl is the LAST live-container verb to leave the core: after it, ZERO check verbs are compiled-in. The wl-exclusive fields live in the plugin’s OWN #WlInput (schema/wl.cue): the verb method enum (the former core #WlMethod, incl. the overlay-/sway- nested methods) plus x/y/x2/y2/button/direction/amount/target/text/key/combo/command/action/query and the artifact validators — command (the exec / sway-msg argv) absorbed from the former shared #Op command modifier; the plugin decodes them from the step’s desugared plugin_input, and only the genuinely shared step matchers still ride core #Op. It dispatches through the provider registry exactly like a built-in (ResolveVerb → grpcProvider → invokeVerbProvider hands it the full #Op). EXEC-based (the third, after record + dbus): the host attaches its live DeployExecutor over the E3b reverse channel and this plugin dials back through the SDK (sdk.ExecutorFromInvoke) to RunCapture the venue’s compositor tools (screenshot pulls the PNG via GetFile) — it owns no podman / SSH machinery and no CDP client (the CLI-only –from-cdp/–from-sway/–from-x11 coordinate translation was dropped; the declarative click method uses X/Y directly). The R10 consumer is a desktop pod bed whose check composes this plugin (the sway-browser-vnc bed’s wl sway-tree + screenshot probes).

The CUE schema below is the authoritative grammar for this plugin’s input. It is the same single source that generates the plugin’s Go parameter types and answers the runtime Describe RPC, so this page cannot disagree with either.

// This plugin's OWN CUE schema — the typed plugin_input for the `wl`
// live-container check verb, served over the Describe channel. It is the SINGLE
// SOURCE for this plugin's params, used two ways (the same contract core `spec`
// and the reference plugin-http use):
//
// 1. GENERATE the Go param struct — `cue exp gengotypes` (driven by task cue:gen,
// which wraps this with `package params` + `@go(params)`) emits
// ../params/cue_types_gen.go, so the provider decodes plugin_input into a TYPED
// struct, never a hand-parsed map.
// 2. VALIDATE authored input AT RUNTIME — the host splices this source onto the
// base (base ++ plugin) and validates every authored `wl` step's plugin_input
// against #WlInput.
//
// Every wl-EXCLUSIVE field lives here (they left core #Op in the schema-compaction
// cutover): the verb `method` enum (the former core #WlMethod, 38 methods incl. the
// overlay-*/sway-* nested ones) plus the input/window/artifact modifiers
// (x/y/x2/y2/button/direction/amount/target/text/key/combo/action/query/command +
// artifact/artifact_min_bytes/artifact_min_dimensions/artifact_not_uniform).
// `command` — the argv for `exec` / `sway-msg` — is ABSORBED from the former shared
// #Op command modifier (the residual #Op `command` field is the command plugin's
// internal rehydration target, never wl's). The step's shared modifiers stay on
// #Op, read off the marshalled step Op: the exit_status/stdout/stderr matchers
// (sdk.VerbVerdict).
//
// SELF-CONTAINED: it references NO base def, so it compiles standalone (gengotypes +
// the SDK's serve-side check) AND splices onto the base (base ++ plugin is a
// def-name collision check, not a base-reference resolver).
#WlInput: {
// method — the wl verb method (the former core #WlMethod enum).
method: "status" | "toplevel" | "windows" | "geometry" | "xprop" | "atspi" | "screenshot" | "clipboard" | "click" | "double-click" | "mouse" | "scroll" | "drag" | "type" | "key" | "key-combo" | "focus" | "close" | "fullscreen" | "minimize" | "exec" | "resolution" | "overlay-list" | "overlay-status" | "overlay-show" | "overlay-hide" | "sway-tree" | "sway-workspaces" | "sway-outputs" | "sway-msg" | "sway-focus" | "sway-move" | "sway-resize" | "sway-layout" | "sway-workspace" | "sway-kill" | "sway-floating" | "sway-reload"
// x/y — desktop-absolute pointer coordinates (click/double-click/mouse/scroll/drag).
x?: int @go(,type=int)
y?: int @go(,type=int)
// x2/y2 — the drag end coordinates.
x2?: int @go(,type=int)
y2?: int @go(,type=int)
// button — pointer button (left/right/middle; empty defaults to left).
button?: string
// text — text to type / the clipboard payload / the overlay text / the exec-adjacent text.
text?: string
// key — a named XKB key for `key` (wtype -k).
key?: string @go(KeyName)
// combo — a key combination for `key-combo` (e.g. ctrl+shift+t).
combo?: string
// direction — scroll direction (up/down/left/right).
direction?: string
// amount — scroll step count (0 defaults to 3).
amount?: int @go(,type=int)
// target — the window/output/workspace target (focus/close/fullscreen/minimize/
// geometry/xprop/overlay name/resolution WxH/sway-* argument).
target?: string
// action — the sub-action selector (atspi tree/find/click; clipboard get/set/clear).
action?: string
// query — the atspi find/click element query (name / role / "name:role").
query?: string
// command — the argv for `exec` / `sway-msg` (absorbed from the former shared
// #Op command modifier).
command?: string
// artifact — the host path a `screenshot` writes its PNG to.
artifact?: string
// artifact_min_bytes — assert the artifact is at least N bytes.
artifact_min_bytes?: int & >=0 @go(ArtifactMinBytes,type=int)
// artifact_min_dimensions — assert the decoded image is at least WxH.
artifact_min_dimensions?: string & =~"^[0-9]+x[0-9]+$" @go(ArtifactMinDimensions)
// artifact_not_uniform — assert the image is not uniformly one color.
artifact_not_uniform?: bool @go(ArtifactNotUniform)
}

See also the candy reference for this candy’s install surface.