CNCjs: one browser front end for five CNC firmwares
A web-based interface for CNC milling controller running Grbl, Marlin, Smoothieware, or TinyG.
At a glance
- What is it?
- CNCjs does not flash anything onto your controller. It opens the serial port, speaks the firmware's text protocol, and turns position reports into a page you can run from a laptop, a phone, or a Raspberry Pi kiosk.
- Who is it for?
- CNCjs is worth understanding as infrastructure rather than as a hobby project, because it is the layer most small CNC machines are missing. A $200 controller board and a $150 stepper motor set can run real jobs, but without a usable interface you are sending G-code through a terminal emulator and reading position reports by eye.
- 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 20 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 24, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A server that reads the serial port, not firmware that flashes it
The project's own description calls it a web-based interface for CNC milling controllers running Grbl, Marlin, Smoothieware, or TinyG, and the homepage is cnc.js.org. The load-bearing word there is interface. Nothing in this repository writes motion code to a flash chip or claims a board's processor time. The real-time work, step pulse generation, limit switch evaluation and feedrate interpolation, all stays on the microcontroller. CNCjs runs on a separate machine, usually the same little computer sitting next to the router, opens the serial port that the controller exposes, speaks that controller's line-oriented text protocol, and turns the resulting stream of position reports into a web page.
The npm manifest spells the architecture out plainly. The package is named cncjs at version 1.11.5, the module entry point is `./dist/cncjs/server-cli.js`, and there are two executables named `cnc` and `cncjs` under `bin/`. A `server-cli` main file is the tell: what gets published is a long-running process that binds a port and holds a serial connection, not a library meant to be imported into your own code. The manifest also declares `preferGlobal: true`, requires Node 18 or newer through its engines field, and carries an MIT licence with Cheton Wu listed as author.
What you get once the port is open
The feature list is where the value becomes obvious. CNCjs offers a six-axis digital readout, so you see commanded and actual position for every axis rather than inferring it from stepper noise. It renders a three-dimensional view of the tool path, which catches a job that is going to plunge somewhere it should not before the spindle is involved. It serves multiple clients at once, so a laptop and a tablet and a pendant can all watch the same machine without fighting over the port.
Beyond the readout there are custom widgets, MDI command buttons mapped to the codes a particular machine needs, and configurable keyboard shortcuts. The README lists tool change support as available since version 1.9.11 and Z-Probe handling among the supported functions. The layout is responsive down to 720 pixels, which is what makes the pendant story work rather than being a separate application.
Supported controllers are listed as Grbl, Grbl-Mega, Marlin, Smoothieware, TinyG with a firmware note recommending version 0.97 build 449.xx, and g2core. The pendants section covers a keyboard, a numpad, an LCD or kiosk mode intended for Raspberry Pi touch displays, a PS3 controller, Raspberry Pi GPIO, and an Alexa skill for voice jogging with per-axis travel limits. Two separate tablet front ends live in sibling repositories, one for a 320 by 240 LCD and one simplified for a production floor.
Three install routes, and the root permission trap
The getting started section starts with Node.js and recommends version 14 or higher, with a node version manager shown as the tidy way to hold several versions side by side. The installation advice that matters comes next. CNCjs should be installed as a non-root user, because the serialport module may fail to install correctly on some platforms such as Raspberry Pi if npm is running with root privileges. The plain command is short:
npm install -g cncjsIf you do want to install as root anyway, the README says to pass the unsafe permission flag so npm runs as the root account, which it spells as `sudo npm install --unsafe-perm -g cncjs`. That flag exists because native module compilation drops privileges by default, and dropping them back to a user who cannot reach the serial devices is precisely the failure the note is warning about.
Two other routes exist. A desktop application is built for Linux, macOS and Windows through an `electron-build/` directory and a set of build scripts in package.json covering macOS on both x64 and arm64, Linux on armv7l and arm64, and Windows on x64. And there is a container: a two-stage Dockerfile based on debian:bullseye that installs Node v18.20.4 through nvm, exposes port 8000, and points its entrypoint at `/opt/cncjs/entrypoint`. Device access still has to be handed to the container, which is the part the Dockerfile does not solve for you.
Configuration files, a firmware simulator, and the development loop
The repository root carries `.cncrc.default`, a documented default configuration, and the `examples/` directory contains a matching `.cncrc` alongside `gcode/`, `grbl-sim/`, `pendant-ps3/` and `pendant-tinyweb/`. Putting a starter configuration and example machine definitions in the repository means you can read what a working setup looks like before you own a working setup.
The more interesting piece is `grbl-simulator/`. A project that talks to a serial protocol is hard to develop against without hardware, because you need a powered machine, a known-good job, and a free evening to test a change. A simulator removes all three. You run the interface, point it at simulated Grbl output, and the parsing, rendering and state logic can be exercised anywhere.
The rest of the tree shows a normal modern JavaScript project rather than a hobby script. Webpack has separate development and production configurations with paired environment files, Babel handles transpilation, ESLint has both an ignore file and a config, and there is a Jest setup file for tests. Release notes are managed through a `.changeset/` directory, which is why the published changelog entries read like structured changesets with attribution and pull request numbers rather than a hand-written release summary.
Recent releases are controller-specific bug fixes
The last three releases describe maintenance of a mature tool rather than new features. Version 1.11.5, published on 2026-09-13, reworked the watch directory modal to add an Add button and a dropzone for uploading files into the configured watch directory, with an upload progress indicator and a file tree that updates in real time through server push events. It also added a progress bar for a running G-code job, and fixed a Grbl status parser to handle the letter-valued `Pn:` and `A:` fields.
The autolevel fix in that same release is the most interesting change. Probe measurements were being recorded at the machine-reported XY coordinate rather than the intended grid node, and because that reported coordinate is quantised by the motor steps, grid lines were being split into near-duplicate entries. Recording the measurement against the node the user actually probed is a small change with a real effect on mesh quality.
Version 1.11.4, on 2026-09-04, was a single fix for Marlin G28 homing. Version 1.11.3, on 2026-08-20, made the console preserve partially typed commands while serial, jog and macro output is rendering, which is the kind of quality-of-life detail that only gets fixed once real users are typing into a busy console every day.
An active MIT project with a real backlog
CNCjs is not archived and the last push to the repository was on 2026-09-21, days after the 1.11.5 release, so this is a project under active work. The scale is 2,647 stars, 623 forks and 141 open issues. The issue count is the one number to hold onto, because it describes a backlog no single maintainer is clearing, and forks at roughly a quarter of stars suggests a meaningful number of people run their own variant.
The topic tags are honest about what the software touches: cnc, cnc-milling-controller, cncjs, g2core, gcode, grbl, linux, marlin, pendant, raspberry-pi, serial, smoothie, smoothieware, tinyg. Linux and serial are there because the software runs on small single-board computers and talks to hardware over a wire, and that combination explains the install notes better than any documentation could.
There is a `CLAUDE.md` at the root alongside `CONTRIBUTING.md`, a `CHANGELOG.md`, an i18next scanner configured separately for the app and the server, which points to genuine multi-language support, and Open Collective badges for backers and sponsors. Browser support is tabulated as yes for Chrome, Edge, Firefox, Opera and Safari, with Internet Explorer explicitly not supported.
Editorial conclusion
CNCjs is worth understanding as infrastructure rather than as a hobby project, because it is the layer most small CNC machines are missing. A $200 controller board and a $150 stepper motor set can run real jobs, but without a usable interface you are sending G-code through a terminal emulator and reading position reports by eye. CNCjs supplies that layer for five different firmware families at once, which is why 2,647 people have starred it and 623 have forked it. Install it as a non-root user, watch the serial permissions on Raspberry Pi rather than reaching for sudo, and remember that a browser tab is not a safety device. The controller enforces the limits and CNCjs is the panel you watch while it does.
Frequently asked questions
What is CNCjs used for?
CNCjs is a full-featured web-based interface for CNC controllers running Grbl, Marlin, Smoothieware or TinyG. It gives you a browser interface with a six-axis digital readout, three-dimensional tool path visualization, custom widgets and MDI command buttons for a machine whose controller speaks one of those firmwares over a serial port.
Which CNC controllers can CNCjs talk to?
The README lists Grbl, Grbl-Mega, Marlin, Smoothieware, TinyG and g2core. For TinyG it recommends firmware version 0.97 build 449.xx. Each controller keeps doing the real-time motion work on its own microcontroller; CNCjs connects over serial and translates the firmware's text protocol into a browser interface.
How do I install CNCjs on Raspberry Pi without breaking serial access?
Install it as a non-root user with `npm install -g cncjs`. The README notes the serialport module may not install correctly on platforms like Raspberry Pi when run as root. If you must use sudo, add the unsafe permission flag as in `sudo npm install --unsafe-perm -g cncjs`, and remember your user still needs permission on the serial device, commonly through the dialout group.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/cncjs-cncjs)