XUL-J is a JSON version of Mozilla's XUL, sent as a stream of small operations. A server, an MQTT device or an unmodified desktop application describes what to show and what can be done; any client decides how it looks. Clicks go back as intents.
{"op":"command","id":"cmd_deploy","label":"Deploy","key":"ctrl+enter"}
{"op":"node","in":"root","tag":"window","id":"win","label":"Deploy console"}
{"op":"node","in":"win","tag":"toolbar","children":[{"tag":"toolbarbutton","command":"cmd_deploy"}]}
{"op":"rows","source":"log","append":[{"t":"12:01","msg":"build ok"}]}▶ Live demo, docs and an LLM generator: xul-j.github.io
| xul-j | The protocol (JSON Schema), browser renderer, SSE server with resume, MQTT transport (the UI as retained topics), terminal renderer, an MCP server for AI agents, demos and end-to-end tests. Node, no framework. |
| net-bridge | Serves unmodified .NET WinForms apps to browsers, one instance per session. Infers flex layout from Dock/Anchor, maps real menus, and shows MessageBox and file dialogs in the browser. Docs |
| java-bridge | The same for Java Swing: layout managers, JOptionPane, JFileChooser, real menus, trapped System.exit. JDK only, Java 8+. Docs |
| xul-j.github.io | The project site, an in-browser demo, and a generator where a model of your choice (OpenRouter, your own key) streams a UI and then acts as its backend. |
A XUL-J stream is a labelled tree with explicit commands and state, which is exactly what an agent needs. The MCP server in xul-j gives any MCP client tools to read the screen, fill fields, run commands, work with tables and right-click menus, answer dialogs and move files. Put it in front of a bridge, and a legacy WinForms or Swing app becomes something an agent can operate reliably.
- Ids and overlays: anything can be patched later, and an element waits for a parent that hasn't arrived yet.
- Commands: intents separate from widgets. Disable one command, and its button, menu item and shortcut follow.
- Broadcasters: named values that attributes observe (
"observes": {"disabled": "busy"}). - Boxes and flex: a half-streamed layout still looks reasonable, and
pendingplaceholders hold space. - Themes as tokens: colours, radius, density and font, never CSS; the viewer's dark mode and contrast needs win.
- Data apart from structure: declare a tree once and stream rows into it (100k rows ≈ 30 DOM nodes).
A working prototype with end-to-end tests for every transport and bridge, not a finished product. The bridges are tested on Linux (Mono's WinForms, OpenJDK Swing); Windows testing, cell editing, a painted fallback for custom controls and authentication are next. Issues, ideas and pull requests are welcome.
All repositories are MIT licensed.