2026-10-08 13:31:33 +00:00
…
2026-10-08 13:31:33 +00:00
2026-10-08 13:31:33 +00:00
…
2026-10-08 13:31:33 +00:00
…

@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_id in slice_info.config is 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 in ts/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 its inherits chain, 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-slicer once in its own temporary directory with the resolved machine, process and filament profiles (--load-settings, --load-filaments), --arrange 1, --slice 0 and, for .gcode.3mf, --export-3mf, in the environment OrcaSlicer's AppImage launcher sets up. OrcaSlicer's command line only accepts a process whose compatible_printers list names the printer, so a process that fits by its condition is written with the printer listed. Progress comes from OrcaSlicer's --pipe named pipe; the result from its result.json; the estimate from the comments in its G-code. The directory is removed once OrcaSlicer has exited.

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.

S
Description
No description provided
Readme
206 KiB
Languages
TypeScript 99.9%