ZEUGHAUS(1) Zeughaus Manual

NAME

zeughaus - edit zeughaus graphs and view what their runners report

SYNOPSIS

zeughaus [join host[:port]/database]

zeughaus --headless --control socket [--size WxH] [--scale factor] [join host[:port]/database]

zeughaus ctl socket command [argument ...]

DESCRIPTION

zeughaus is the editor. It edits the graph held in a session's store and draws what the runners of that session report: values, node errors, frames and terminals. It never executes a node; a graph runs in the zeughaus-runner it names (see zeughaus-runner(1)). Any number of editors, on this machine or others, may join one session.

At start the editor connects to the store of the session it is given, or to the default session 127.0.0.1:3000/zeughaus. It finds every runner in the store's runtime table and dials each one's endpoint over weida, presenting client.pem from its state directory. The editor never creates that key: without it, it prints [editor] no client identity in ... and shows no values. See zeughaus-files(5).

Without a store the editor still starts. It edits a local scratch graph under the tab bar section Local; nothing computes it, the status bar says so, and it is gone on close unless saved as a file.

The window is undecorated and draws its own titlebar, tab bar and resize grips. Its title is Zeughaus Editor; on Linux its application id (X11 WM_CLASS, Wayland app_id) is net.doodleshnookie.Zeughaus. Closing the window first flushes settings edits still held back (400 ms after the last keystroke) to the store. Keys, the command palette and the workspace are described in zeughaus-keys(7); the node types in zeughaus-nodes(7).

OPTIONS

The windowed editor reads one argument, join; everything else on its command line is ignored. --headless and its options, and the ctl command, exist only in a binary built with the remote feature (cargo build -p zeughaus --features remote); without it they are ignored too and a window opens.

join host[:port]/database
Join the session in database database on the store at host. port defaults to 3000; a bare database means the store on 127.0.0.1:3000. Without join, the editor uses 127.0.0.1:3000/zeughaus and offers this machine's LAN address in its place as the token others join with ("Session / Copy Session ID" in the palette). The same token shape is what zeughaus-runner join takes.
--headless
Run the real application without a window, rendered offscreen by a hardware wgpu adapter, and take input from the control socket. There is no software fallback: without an adapter the process prints [remote] no wgpu adapter and exits 1. Store and runner connections, subscriptions and signals behave as in a window. The clipboard is kept in memory and never touches the desktop's, and the save and load file dialogs are refused with a hint. Any argument other than join and the options below is an error.
--control socket
The Unix socket the headless editor listens on. Required with --headless. A stale socket file at that path is replaced; the file is removed when the host exits.
--size WxH
Logical size of the pretend window, each side at least 1. Default 1280x800, the size a window opens with.
--scale factor
Scale factor, a positive number. Default 1. Screenshots and recordings are the logical size times this factor.

CONTROL COMMANDS

zeughaus ctl socket command [argument ...] connects to a headless editor, sends the words joined by spaces as one line, and prints the one-line reply on standard output: ok, possibly followed by a result, or err reason. Coordinates are logical pixels and may be fractional. Pointer and key commands deliver their events one at a time with the application's loop running between them, as a window would across frames, and reply once the loop has gone quiet (at most 250 ms). Each connection is served on its own thread, so a waiting wait-idle does not hold up another client. A relative screenshot or record path is resolved against the working directory of ctl, not of the host.

size
Reply ok W H factor: the logical window size and the scale factor.
move X Y [MS]
Move the pointer to X Y. With MS the move starts at the current position and is spread over that many milliseconds, one step per 16 ms.
down [button]
Press a mouse button where the pointer is: left (default), right or middle.
up [button]
Release a mouse button, as for down.
click X Y [button]
Move to X Y, press and release button (default left).
dblclick X Y
Two left clicks at X Y.
drag X1 Y1 X2 Y2 [steps] [MS]
Press the left button at X1 Y1, move to X2 Y2 in steps evenly spaced moves (a positive integer, default 10), release. MS paces the moves over that many milliseconds; without it each step waits only for the loop to settle.
scroll X Y DY [DX]
Move to X Y and turn the wheel by DY lines vertically and DX lines horizontally (default 0).
key chord
Press and release one key. chord is [ctrl+][shift+][alt+][super+]key, the prefixes in any order and case. key is one character or one of enter, escape, tab, backspace, delete, space, arrowup, arrowdown, arrowleft, arrowright, home, end, pageup, pagedown, f1 to f12. shift+ upper-cases a letter as a US layout does; with ctrl+, alt+ or super+ the key is a shortcut and types no text.
type text
Type the rest of the line, one key press per character, without modifiers.
find text
Reply ok X Y W H, the visible bounds of the first widget whose text is exactly text; err not found or err not visible otherwise. Inside the node graph the bounds are graph layout coordinates, not screen coordinates.
screenshot path
Render a frame with the pointer's hover state and write it to path as an RGBA PNG. Reply ok path WxH in physical pixels.
record path
Start a recording: frames at 30 fps are piped into ffmpeg, which writes an H.264 MP4 (libx264, yuv420p, +faststart) to path. The pointer is painted in, with a ring around its tip while the left button is down. Reply ok recording path WxH. Needs ffmpeg on PATH; one recording at a time (err already recording path).
record-stop
End the recording and wait for ffmpeg to finish the file. Reply ok path n frames secondss, or err not recording.
resize W H
Set the logical window size, each side at least 1. Refused while recording (err stop the recording first): a video has one frame size.
scale factor
Set the scale factor, a positive number. Refused while recording.
clip
Reply ok followed by the text on the in-memory clipboard, or a bare ok when it is empty.
clip-set text
Put the rest of the line on the in-memory clipboard.
wait-idle [MS]
Reply ok idle once no redraw is due and nothing has happened for MS milliseconds (default 200); err timeout after 10 s. The periodic tick and the store poll do not count as something happening.
restart
Restart the editor as SIGUSR1 does (see SIGNALS) and reply ok restarting. The new process binds the same socket path again, so a client polling size sees it come back.
quit
Close the editor as the window's close button does: held settings edits are flushed and the runner connections closed. Reply ok; the host then exits 0 and removes the socket.

GRAPH FILES

Ctrl+S saves and Ctrl+O loads a graph file (on macOS also Cmd+S and Cmd+O), through the system's file dialog with the filters Zeughaus Graph (*.zgh) and JSON (*.json). They are keyboard shortcuts, not palette entries. Save writes every node and edge this editor holds as one .zgh document. Load replaces the document this editor holds and writes nothing to the store; a file that does not parse is ignored. The format is described in zeughaus-files(5).

THE BROWSER BUILD

The editor also compiles to wasm32-unknown-unknown and runs in a browser tab (trunk serve in the zeughaus/ crate directory, see zeughaus-install(8)). The browser needs WebGPU: iced_nodegraph has no WebGL fallback. The browser editor edits locally. It does not connect to a store, so it neither sees nor changes a session, and no runner computes what it shows. It has no terminals, none of the native-only plugins (capture, db, record, llm), no file dialogs, and no state directory: the bundled themes are the whole choice and no preference outlives the tab. The canvas is rectangular, without the native window's rounded corners.

ENVIRONMENT

ZEUGHAUS_STATE_DIR
The state directory, when set and not empty. The editor has no --state-dir option: an editor that is to use the credentials of a runner started with --state-dir path needs ZEUGHAUS_STATE_DIR set to that path.
XDG_STATE_HOME, HOME
Without ZEUGHAUS_STATE_DIR, the state directory is $XDG_STATE_HOME/zeughaus, else $HOME/.local/state/zeughaus. HOME also locates the SpacetimeDB client token (see FILES).
ZEUGHAUS_RESTORE
Set by the editor itself when it restarts: the path of the restore file the new process reads at start and deletes. A second start with the same environment is a fresh one.
WAYLAND_DISPLAY
Not read by zeughaus; it decides, through winit, whether the window is a Wayland window. A Wayland window carries no icon (winit 0.30 cannot set one; the compositor takes it from the desktop entry named after the application id, which deploy/install.sh installs), and a restart cannot restore its position. Screen capture is decided by the runner's environment, not the editor's (see zeughaus-runner(1)).

FILES

All described in zeughaus-files(5).

<state-dir>/client.pem
The client identity the editor presents to runners. Read, never created.
<state-dir>/editor.toml
The theme and the tab bar's placement, written when either changes.
<state-dir>/themes/*.toml
WezTerm colour schemes, offered as themes by file name. Read at start.
<state-dir>/restore-<pid>.json
What a restarting editor hands to the process that replaces it.
~/.spacetimedb_client_credentials/zeughaus-<host>-<database>
The token the store issued to this machine for that store and database, saved by the SpacetimeDB SDK on every connect.

SIGNALS

SIGUSR1
Restart in place (unix). The editor flushes settings edits still held back, writes <state-dir>/restore-<pid>.json, closes its runner connections and execs the binary at the path it was started from, with the same arguments and ZEUGHAUS_RESTORE naming the file. A binary rebuilt at that path in the meantime is the one that starts. The file holds the window's size and maximized state, the tab in front and the focused pane, collapsed sections and groups, each graph's camera, resized node sizes, the selection, an open palette with its input, a rename in progress, terminal scroll-back, nested views open in a section without a runner, and, without a store, the scratch document. Tabs, panes, the selection and scroll positions are applied as the runners' snapshots arrive, for up to 15 s. The window's position is not restored: a Wayland client can neither read nor set it. The handler is installed in the windowed and the headless editor alike.

EXIT STATUS

zeughaus ctl exits 0 when the reply starts with ok, 1 on an err reply or when the host cannot be reached, and 2 on a malformed command line (no socket or no command). zeughaus --headless exits 0 after quit, 1 when it finds no wgpu adapter or cannot listen on the socket, and 2 on a malformed command line.

EXAMPLES

Start an editor on the default session, or join a session on another machine:

zeughaus
zeughaus join 10.0.0.8:3000/zeughaus

Build the headless editor, run it against its own store database and state directory, and drive it:

spacetime publish --server local zeughaus-agent --module-path zeughaus-module -y
cargo build -p zeughaus --features remote -p zeughaus-runner
ZEUGHAUS_STATE_DIR=/tmp/zh-agent target/debug/zeughaus-runner join 127.0.0.1:3000/zeughaus-agent &
ZEUGHAUS_STATE_DIR=/tmp/zh-agent target/debug/zeughaus --headless --control /tmp/zh-agent.sock join 127.0.0.1:3000/zeughaus-agent &
target/debug/zeughaus ctl /tmp/zh-agent.sock wait-idle 500
target/debug/zeughaus ctl /tmp/zh-agent.sock key ctrl+space
target/debug/zeughaus ctl /tmp/zh-agent.sock screenshot palette.png
target/debug/zeughaus ctl /tmp/zh-agent.sock key escape

Record a slow drag as a video:

zeughaus ctl /tmp/zh-agent.sock record drag.mp4
zeughaus ctl /tmp/zh-agent.sock drag 400 300 700 420 30 1000
zeughaus ctl /tmp/zh-agent.sock record-stop

Restart the newest editor in place after installing a new build:

kill -USR1 "$(pgrep -nx zeughaus)"

FUTURE DIRECTIONS

Not built: a browser editor that syncs with the store. The wasm build edits locally only.

SEE ALSO

zeughaus-runner(1), zeughaus-files(5), zeughaus-keys(7), zeughaus-nodes(7), zeughaus-architecture(7), zeughaus-install(8), zeughaus-glossary(7)

zeughaus/src/main.rs, zeughaus/src/remote/mod.rs, zeughaus/src/remote/host.rs, zeughaus/src/remote/ctl.rs, zeughaus/src/restart.rs, zeughaus/src/app/restore.rs, zeughaus/src/prefs.rs, zeughaus/Trunk.toml

install(8)source