@push.rocks/smartslicer
Headless 3D-print slicing for Node.js with the OrcaSlicer command line. smartslicer installs a pinned OrcaSlicer release, resolves OrcaSlicer's bundled printer, process and filament profiles (Bambu Lab, Prusa, Voron and other Klipper printers, and many more), and slices STL or 3MF models to plain G-code or to the .gcode.3mf project files Bambu Lab printers print from.
Issue Reporting and Security
For reporting bugs, issues, or security vulnerabilities, please visit community.foss.global/. This is the central community hub for all issue reporting. Developers who sign and comply with our contribution agreement and go through identification can also get a code.foss.global/ account to submit Pull Requests directly.
Install
pnpm add @push.rocks/smartslicer
pnpm exec smartslicer install
smartslicer install downloads OrcaSlicer 2.4.2 (the Ubuntu 24.04 AppImage, 138 MB) from its official GitHub release, verifies its SHA-256 digest, and unpacks it (379 MB) into $SMARTSLICER_HOME, else $XDG_CACHE_HOME/smartslicer, else ~/.cache/smartslicer. It needs no FUSE. Run it once, when you build the machine or image, not per request; it returns at once when OrcaSlicer is already installed. --dir <directory> installs elsewhere, and --appimage <file> installs from a local copy of the pinned AppImage, which is verified the same way. From code, call await new SmartSlicer().install().
OrcaSlicer is installed explicitly rather than from a postinstall script, because pnpm does not run dependency lifecycle scripts by default and a server should not download 138 MB on its first request.
Platforms and system libraries
OrcaSlicer is pinned for Linux x64 and arm64 (glibc 2.39 or newer, e.g. Ubuntu 24.04 and the ht-docker-node:ubuntu-node image). SmartSlicer.isPlatformSupported() tells you at runtime; elsewhere, e.g. on macOS, install() and slicing reject with EPLATFORM.
OrcaSlicer is one binary for its GUI and its command line, so it links GTK, WebKitGTK and OpenGL even when it only slices. Slicing needs no display, but the libraries must be installed. On Ubuntu 24.04:
apt-get install -y --no-install-recommends libwebkit2gtk-4.1-0 libglu1-mesa libopengl0 libsecret-1-0 libsm6
They add about 510 MB to the ht-docker-node:ubuntu-node image (about 170 MB compressed). smartslicer also uses mkfifo from coreutils for OrcaSlicer's progress pipe.
A Docker image's production stage:
FROM code.foss.global/host.today/ht-docker-node:ubuntu-node AS production
RUN apt-get update \
&& apt-get install -y -q --no-install-recommends libwebkit2gtk-4.1-0 libglu1-mesa libopengl0 libsecret-1-0 libsm6 \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
ENV SMARTSLICER_HOME=/opt/smartslicer
COPY --from=build /app /app
RUN node_modules/.bin/smartslicer install
Usage
import { SmartSlicer } from '@push.rocks/smartslicer';
const slicer = new SmartSlicer();
const result = await slicer.slice({
model: stlBuffer, // binary or ASCII STL, or 3MF
name: 'bracket',
machine: 'Bambu Lab X1 Carbon 0.4 nozzle',
process: '0.20mm Standard @BBL X1C',
filament: 'Bambu PLA Basic @BBL X1C',
output: 'gcode.3mf', // or 'gcode'
});
result.filename; // 'bracket.gcode.3mf'
result.file; // Buffer
result.estimate; // { printTimeSeconds: 980, filamentGrams: 3.94, filamentMm: 1298.81 }
result.warnings; // warnings OrcaSlicer reported while slicing
await slicer.stop();
The model is arranged on the plate: a single object lands in the middle of the bed, resting on it. Its orientation is kept.
Profiles
Profiles are OrcaSlicer's system presets, named as in OrcaSlicer's GUI:
const machines = await slicer.listMachines();
// [..., { name: 'Bambu Lab X1 Carbon 0.4 nozzle', vendor: 'BBL', model: 'Bambu Lab X1 Carbon',
// nozzleDiameter: 0.4, gcodeFlavor: 'marlin', printableArea: [[0, 0], [256, 0], [256, 256], [0, 256]],
// printableHeight: 250, defaultProcess: '0.20mm Standard @BBL X1C',
// defaultFilaments: ['Bambu PLA Basic @BBL X1C'] }, ...]
const processes = await slicer.listProcesses('Prusa MK4S 0.4 nozzle');
// [..., { name: '0.20mm SPEED @MK4S 0.4', vendor: 'Prusa', layerHeight: 0.2 }, ...]
const filaments = await slicer.listFilaments('Bambu Lab X1 Carbon 0.4 nozzle');
// [..., { name: 'Bambu PLA Basic @BBL X1C', vendor: 'BBL', filamentType: 'PLA', filamentId: 'GFA00' }, ...]
const profile = await slicer.getProfile('process', '0.20mm Standard @BBL X1C');
profile.settings.layer_height; // '0.2', with the whole inherits chain resolved
Processes and filaments are listed the way OrcaSlicer's preset selection offers them: a profile fits a printer when its compatible_printers list names the printer, or, with an empty list, when the printer meets its compatible_printers_condition (Prusa's MK4S and CORE One profiles select printers by their notes and nozzle diameter). Filaments come from the printer's vendor first, then from OrcaSlicer's filament library, minus library filaments the vendor replaces with its own profile of the same name. filamentId is the Bambu Lab filament id the AMS reports for a tray.
slice() checks the same compatibility and rejects a process or filament that does not fit the printer with EPROFILEMISMATCH. filament takes one profile name or a list, one per extruder or AMS slot; the model prints with the first.
Overrides
await slicer.slice({
model,
machine: 'Prusa MK4 0.4 nozzle',
process: '0.20mm Standard @MK4',
filament: 'Prusa Generic PLA @MK4',
output: 'gcode',
overrides: {
layerHeight: 0.15, // layer_height
infillDensity: 25, // sparse_infill_density, percent
supports: 'tree', // 'none' | 'normal' | 'tree': enable_support and support_type
brimWidth: 5, // outer brim in mm; 0 turns the brim off
settings: { wall_loops: 3, curr_bed_type: 'Textured PEI Plate' }, // any OrcaSlicer setting
},
});
Overrides go to OrcaSlicer's command line, which takes precedence over the profiles; settings takes precedence over the typed overrides. Numbers and booleans become 12.5, 1 and 0; arrays of numbers or booleans are joined with commas and arrays of strings with semicolons. OrcaSlicer rejects unknown settings and unparsable values, which slice() reports as EOVERRIDE.
Progress, timeouts and concurrency
const slicer = new SmartSlicer({
installDir: '/opt/smartslicer', // default: see Install
concurrency: 2, // slices that run at once; others wait (default 1)
sliceTimeoutMs: 120_000, // OrcaSlicer's run time per slice (default 300000)
});
await slicer.slice({
...options,
timeoutMs: 60_000,
onProgress: ({ percent, message }) => console.log(`${percent}% ${message}`), // e.g. '75% Generating G-code'
});
OrcaSlicer slices on all cores, so a concurrency of 1 or 2 is usually right. A slice that exceeds its timeout is killed. stop() kills running slices, rejects waiting ones, and makes later calls reject with ESTOPPED.
Errors
Failed calls reject with a SmartSlicerError carrying a code. Errors from OrcaSlicer also carry its return code and the last lines it printed:
| Code | Meaning |
|---|---|
EPLATFORM |
No OrcaSlicer build is pinned for this platform. |
ENOTINSTALLED |
OrcaSlicer is not installed; run smartslicer install. |
EINSTALL |
Downloading, verifying or unpacking OrcaSlicer failed. |
EPROFILE |
A profile does not exist or cannot be resolved. |
EPROFILEMISMATCH |
The process or a filament does not fit the printer. |
EMODEL |
The model is not an STL or 3MF file, or OrcaSlicer cannot read it. |
EFIT |
The model does not fit on the printer's plate. |
EOVERRIDE |
An override names an unknown setting or has an invalid value. |
ESLICE |
OrcaSlicer failed to slice; the message is OrcaSlicer's. |
ETIMEOUT |
The slice exceeded its timeout and OrcaSlicer was killed. |
ESTOPPED |
The slicer was stopped. |
EPROCESS |
OrcaSlicer could not be started, crashed or left no result, e.g. because a system library is missing. |
import { SmartSlicerError } from '@push.rocks/smartslicer';
try {
await slicer.slice(options);
} catch (error) {
if (error instanceof SmartSlicerError && error.code === 'EFIT') {
console.log(error.message, error.orcaReturnCode); // OrcaSlicer's message, -50
}
}
Output for Bambu Lab printers
A .gcode.3mf holds the sliced plate as Bambu Lab printers expect it: Metadata/plate_1.gcode with its MD5 in Metadata/plate_1.gcode.md5, Metadata/slice_info.config with the print time, filament weight and the filament ids for AMS mapping, Metadata/plate_1.json, the project and model settings, and the model itself.
It lacks two things OrcaSlicer's GUI adds:
- Plate images (
Metadata/plate_1.png,plate_no_light_1.png,top_1.png,pick_1.png), which printers and Bambu Handy show as the print preview. OrcaSlicer 2.4.2's command line requests an OpenGL context of version 3.4, which does not exist, so it never renders them on Linux, with or without a display (fixed upstream after 2.4.2). Plain G-code lacks its embedded thumbnails for the same reason. printer_model_idinslice_info.configis empty: the command line looks the model id up in a BambuStudio file layout that OrcaSlicer's resources do not have.
How it works
SmartSlicer.install()downloads the AppImage pinned ints/orcaslicer.ts, checks its size and SHA-256 digest, unpacks it with its own--appimage-extract, and moves the tree into place with a single rename, so concurrent or interrupted installs never leave a partial installation behind. OrcaSlicer's license and source location (notices/orcaslicer/) are copied into the installation.- Profiles are read from the installation's
resources/profiles. A profile is merged over itsinheritschain, root first, as OrcaSlicer loads its vendor bundles: parents come from the same vendor, and filaments may also inherit from OrcaFilamentLibrary. - Each slice runs
orca-sliceronce in its own temporary directory with the resolved machine, process and filament profiles (--load-settings,--load-filaments),--arrange 1,--slice 0and, for.gcode.3mf,--export-3mf, in the environment OrcaSlicer's AppImage launcher sets up. OrcaSlicer's command line only accepts a process whosecompatible_printerslist names the printer, so a process that fits by its condition is written with the printer listed. Progress comes from OrcaSlicer's--pipenamed pipe; the result from itsresult.json; the estimate from the comments in its G-code. The directory is removed once OrcaSlicer has exited.
License and Legal Information
This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the license.md file.
This package does not contain OrcaSlicer. smartslicer install downloads an unmodified OrcaSlicer release from its official GitHub releases and verifies it against the SHA-256 digest pinned in this package. OrcaSlicer is licensed under the GNU Affero General Public License, version 3; its license text and the location of its corresponding source are in notices/orcaslicer/. OrcaSlicer is a separate program that smartslicer runs as a child process.
Please note: The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.
Trademarks
This project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH or third parties, and are not included within the scope of the MIT license granted herein.
Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines or the guidelines of the respective third-party owners, and any usage must be approved in writing. Third-party trademarks used herein are the property of their respective owners and used only in a descriptive manner, e.g. for an implementation of an API or similar.
Company Information
Task Venture Capital GmbH Registered at District Court Bremen HRB 35230 HB, Germany
For any legal inquiries or further information, please contact us via email at hello@task.vc.
By using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.