CLI tool
sidorares/node-x11 avatar
sidorares/node-x11

node-x11: A JavaScript client for the X11 protocol, from core requests to DRI3 GPU frames

sidorares/node-x11 is an open-source project for practical engineering and operations.

536 stars75 forksJavaScriptMIT

At a glance

What is it?
node-x11 implements the X11 wire protocol in JavaScript for Node.js and browsers, covering core requests plus extensions like GLX, DRI3, and Present. It is a low-level client library, not a GUI toolkit, and its value depends on how much protocol coverage you need.
Who is it for?
Adopt node-x11 if you are building a window manager, compositor, or remote display tool in JavaScript and need direct access to X11 requests without a C extension. It is also a good fit for browser-based demos or testing against its bundled pure-JavaScript X server.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 3 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

What node-x11 actually solves

node-x11 is a client-side implementation of the X11 protocol in pure JavaScript. It solves the problem of talking to an X server from Node.js or a browser without going through a native binding like node-xcb or a C library. The README lists core protocol support plus extensions: Xrender, Damage, Composite, Big-Requests, Dpms, Screensaver, XFixes, Shape, XTest, XC-Misc, GLX, DRI3, Present, and Apple-WM. The target audience is developers building window managers, compositors, remote display tools, or VNC clients in JavaScript. The project lists several such projects in its "In use" section, including tiling window managers and a VNC client. It is not a GUI toolkit; it gives you raw requests and events. If you want buttons and text boxes, you would build them on top, as the ntk toolkit does.

How the protocol flow works

The library speaks the X11 wire protocol. You create a client connection, get a display object, and then issue requests through the client object. The README's example shows the core flow: call x11.createClient, receive a display, use display.client to send requests, and allocate IDs with X.AllocID(). Then you call X.CreateWindow with parameters like parent, geometry, and event masks. The event mask is a bitmask built from x11.eventMask, for example Exposure and PointerMotion. After creating a window, you map it with X.MapWindow. This is the same request pattern you would see in C with Xlib, but without the C library. The library handles the connection, serialization, and event parsing. For extensions, you would enable them and then issue extension-specific requests. The documentation points to guides for custom transports, which shows that the connection layer is pluggable: you can register a custom protocol prefix or pass any duplex stream to createClient. That design is what makes browser support possible.

Getting it running: install and first window

Installation is straightforward: run npm install x11. The README gives a Windows note: you need XMing or Cygwin/X, because you need an X server to connect to. On Linux, you would use the system X server. The example code is complete enough to copy: require('x11'), call createClient, and in the callback create a window. The key details are that you must allocate an ID with X.AllocID() before creating a window, and you pass a configuration object for parameters like eventMask. The example uses Exposure and PointerMotion events. After creation, you map the window to make it visible. The library also supports a bundled pure-JavaScript X server in lib/xserver, which runs in the browser playground. That server lets you run node-x11 code against a JavaScript implementation of an X server, including GLX over WebGL. This is a notable feature for testing without a real X server.

The DRI3 and Present path: GPU frames as dma-buf pixmaps

The most technically interesting part is the modern direct-rendering path. The README says the library implements DRI3 and Present, and the docs/ext/dri3.md file covers how GPU frames become dma-buf pixmaps. This means you can get actual GPU-rendered frames from a client and present them via the Present extension. This is not a common feature in X11 client libraries, especially in pure JavaScript. The advantage is that you can build a compositor or remote display that uses hardware acceleration without writing C code. The trade-off is complexity: DRI3 involves passing file descriptors over the connection, which is not a standard socket operation. The README notes that under Bun, file descriptor passing works, and uniquely, descriptors can also be received. That is a specific constraint. On Node.js, receiving descriptors may not be supported, though sending them might work. The documentation does not say explicitly for Node.js, so you should verify that before relying on DRI3.

Where it is the wrong tool

node-x11 is not for everyone. If you need a high-level GUI toolkit, you should look elsewhere; the project is low-level by design. The README lists ntk as a higher-level toolkit built on top, so you could use that, but ntk is a separate project with its own maintenance. Another limitation is that the library assumes an X server is available. On Windows, you must install XMing or Cygwin/X, which adds setup friction. The browser support is real, but it requires a custom transport and a server that speaks the protocol, which limits its use to demos or specific applications. The pure-JavaScript X server in lib/xserver may not implement every extension or every corner of the core protocol, so you might hit unimplemented features when testing complex code. Also, the library is a client implementation, not a server, so you cannot use it to create an X server yourself.

Alternatives and how they differ

The most direct alternative is XCB, a C library with a different approach: it is generated from XML protocol descriptions and gives you a more complete and battle-tested implementation. XCB is used by many real X applications, and it is the basis for some JavaScript bindings. The README lists several other implementations: Python Xlib, Go's xgb, and Java bindings. For JavaScript specifically, there is no other pure-JavaScript client with the same extension coverage, but you could use a C binding like node-xcb if it exists. The key difference is that node-x11 is pure JavaScript, which means no native compilation and easier deployment, but it may lag behind XCB in protocol coverage or performance. XCB is also more established and has a larger community. If you need the latest X11 extensions or maximum reliability, XCB might be safer. If you want to stay in JavaScript and avoid native modules, node-x11 is the only viable option among the listed implementations.

Maintenance, license, and upgrade cost

The repository is active, with the last push in August 2026 and recent releases v4.0.0, v4.0.1, and v4.1.0. The v4.0.0 release suggests a major version change, which could include breaking API changes. The README does not detail what changed, so you should read the release notes before upgrading from older versions. The license is MIT, which is permissive and allows commercial use without copyleft obligations. That is a positive for adoption. The project has documentation and a playground, which helps reduce the learning curve, but the low-level nature means you will spend time understanding X11 concepts like event masks and ID allocation. The upgrade cost depends on how much you rely on the library's internals. If you use only the core protocol, upgrades may be smooth. If you use DRI3, be prepared for potential changes in file descriptor handling. Also, the library depends on Node.js streams, so you need a Node version that supports the stream API you use.

Editorial conclusion

Adopt node-x11 if you are building a window manager, compositor, or remote display tool in JavaScript and need direct access to X11 requests without a C extension. It is also a good fit for browser-based demos or testing against its bundled pure-JavaScript X server. Avoid it if you need a high-level widget toolkit or if your target platform has no X server, since the library speaks the wire protocol and expects a server. Before adopting, verify that the extensions you require (especially DRI3 and Present) work on your display server and that your Node.js version supports the stream and file descriptor handling used by the library. The project is actively maintained as of August 2026, but check the release notes for v4.0.0 and v4.1.0 to confirm API changes.

Official sources

  1. Official documentation
  2. Official README
  3. Project repository
  4. Release notes
Community notes

Community notes