Skip to main content

deli-slicer

A CLI-first slicer front end for 3D printing.

deli keeps a print job as a plain-text deli.toml in the current directory. Each subcommand edits that file and exits, so a print is set up with a few commands in a shell and a file you can read, with nothing else to open. Slicing is done in-process by PrusaSlicer's libslic3r, and the printer profiles come from OrcaSlicer's repository, converted by deli, so neither slicer needs to be installed: the printers OrcaSlicer knows are a deli setup away on a machine that has never had a slicer on it.

A folder of models is the project, and there is nothing to save: every command updates deli.toml as it goes. Come back months later, cd into the folder, and deli send --print prints the same parts, placed the same way, with the same profiles and settings.

Everything deli prints is plain text, with --json where a program wants data, and every command is one a shell runs. That makes deli simple for humans to use directly or through an AI: the repository ships a skill that briefs an assistant (see "Using deli from an AI assistant"). When something needs seeing, deli view shows the parts and the sliced G-code in your browser, and even there every change it makes is a deli command you could have typed.

deli setup asking a Klipper printer at its address what it is and choosing the Voron 2.4 that fits, then adding a Benchy, deli status, slicing it, the sliced Benchy building up layer by layer in deli view, and deli send --print

deli setup                # once: tab completion, your printer, and how to reach it
deli add 3DBenchy.stl
deli slice                # how long it will take, and how much filament
deli view                 # the sliced Benchy in your browser, layer by layer
deli send --print         # to the printer, and start it

Status: early. Everything above works; deli converts and slices for most of the printers OrcaSlicer knows, but has printed on only two so far. See "Not done yet" at the end.

Motivation

deli came out of my frustrations with the slicers I was using:

  • PrusaSlicer has no settings built in for my printer, an Elegoo Centauri Carbon.
  • OrcaSlicer does, but it crashes often and generally does not like my PC.
  • OrcaSlicer supports lots of printers, but it is somewhat focused on Bambu Lab's.
  • I have two printers, the Elegoo and a Voron, and want to configure both easily. I found myself using both slicers, plus Cura now and then.
  • Both have bewildering settings screens, mostly because there are so many settings and options. Most of them stay at their defaults, so finding a particular one means hunting and guessing, and the guess is often wrong.

So deli takes a printer's settings from OrcaSlicer, slices with PrusaSlicer's engine, and has no window to open. Every printer is a profile in one library, chosen for each print, so one tool can serve them all. A print is a short text file that holds only what you changed, and you change a setting by its name: deli set infill 20%. When the name is not quite right, deli suggests the ones that are close.

The longer story, with clips of each part, is in the blog post deli: A 3D Printer Slicer That Lives in My Shell.

Install

deli is a Python package with PrusaSlicer's slicing engine compiled in, on PyPI as deli-slicer. On Linux (and Windows, in WSL: see below) or macOS, with uv:

uv tool install deli-slicer

(pipx install deli-slicer does the same.) Without uv, one line installs it first, then deli:

curl -LsSf https://raw.githubusercontent.com/dcruver/deli-slicer/main/install.sh | sh

Either way uv fetches Python 3.12 if you don't have it. Then run deli setup. Later, deli update installs the latest release the same way (--check only says whether there is one; deli update 0.17.0 a particular release), or run the script again, with DELI_VERSION=0.17.0 in front of sh for a particular release. deli status mentions a newer release when one is out, looking once a day; deli config update_check false stops it looking.

The wheels

Each release is four wheels, one per platform with the engine inside, on PyPI and on the release page; nothing needs building, and pip install deli-slicer in an environment of your own takes them too. The Linux wheels need glibc 2.28 or newer, which most distributions from 2019 on have: Debian 10, Ubuntu 18.10, RHEL/Alma/Rocky 8, Fedora 29 and later. The macOS wheels need macOS 11 (Apple Silicon) or 10.15 (Intel). All of them need Python 3.12 or newer. uv itself runs on any of those Linuxes but needs macOS 13; on an older Intel Mac, install Python 3.12 and use pipx install deli-slicer, or pip install deli-slicer in a virtual environment of your own.

Releases up to 0.16.0 were on GitHub only, under the package name deli, which on PyPI is another project. A deli that old cannot deli update past it: run the install line above once more, which also clears the old package's environment away.

On Windows, in WSL

There is no Windows wheel; on Windows, deli runs in WSL, Windows' own Linux, with the Linux x86-64 wheel. In PowerShell, once:

wsl --install

Then, in the Ubuntu terminal it opens:

curl -LsSf https://raw.githubusercontent.com/dcruver/deli-slicer/main/install.sh | sh

It should work as on Linux (see below for how far that has been checked), with a few things to know:

  • Your printer: give deli setup its IP address, or a name your router knows. Names ending in .local often don't resolve inside WSL. On Windows 11, WSL's mirrored networking (networkingMode=mirrored in .wslconfig) puts WSL on your network like any other program.
  • deli view: open the address it prints in your Windows browser.
  • Your models: Windows' folders are under /mnt/c/, so C:\Users\you\Downloads is /mnt/c/Users/you/Downloads. Reading from there is slower than from WSL's own folders, but fine for a few models.

How far this has been checked: nobody has used deli on a Windows PC yet. What is checked is automatic: for each release, a GitHub Actions job on one of GitHub's Windows Server machines sets up WSL 2 with Ubuntu 24.04, installs the wheel with uv (not with the one-line script), and runs deli's test suite, which slices but talks only to fake printers. deli setup and deli send with a real printer, deli view in a Windows browser, the networking notes above and models under /mnt/c/ are untested; they come from how WSL works, not from trying them. If you run deli on Windows, an issue saying how it went would help.

Then let deli set itself up:

deli setup

It sets up tab completion for your shell, then asks for your printer's hostname or IP address and asks the printer what it is: a Klipper printer says its nozzle, bed and height, and setup lists OrcaSlicer's printers that fit; an Elegoo printer says its model, and setup asks only the nozzle size. The printer is imported with Orca's process and filament for it, named as the printer names itself (a Klipper printer's hostname, or the address's first label), given the settings that fit what it reported (no taller prints than its Z travel, the material passed to a PRINT_START that reads it), and its address kept for deli send. A printer deli cannot reach is found by any words of its name instead. A Bambu Lab printer is recognised, but deli cannot send to one yet. Run it again to add or change a printer. Everything it does can also be done step by step, as the next sections show.

From source

The first build compiles PrusaSlicer's dependencies (about 35 minutes) and then the engine (about 15), and needs CMake, Ninja, a C++17 compiler and about 5 GB of disk. PLAN.md has the details under "Dependency build"; the short version:

git clone https://github.com/dcruver/deli-slicer.git && cd deli-slicer
git submodule update --init --depth 1
ci/build-deps.sh     # PrusaSlicer's dependencies, into build/deps
make install

make install installs deli as a uv tool pointing at the checkout, so git pull updates it; after a change to the C++ binding, make reinstall. make wheel builds a wheel in dist/ to give to someone else.

Shell completion

Completion covers commands, options, your printers and their nozzles, printers, filaments and processes (yours and OrcaSlicer's), the parts of the current print, setting names and their short names, and config keys. deli setup sets it up; by hand, it is one of:

eval "$(deli completion bash)"      # in ~/.bashrc
eval "$(deli completion zsh)"       # in ~/.zshrc
deli completion fish > ~/.config/fish/completions/deli.fish

deli setup puts bash's in ~/.local/share/bash-completion/completions/ when the bash-completion package is installed, which loads it with nothing in ~/.bashrc, and adds the line to ~/.zshrc only if you say yes.

Set up a printer

To slice, deli needs three things for your printer: the printer itself (bed size, nozzle, start and end G-code), a process (layer height, speeds, infill: what PrusaSlicer calls print settings) and a filament. You don't write any of them. deli converts them from OrcaSlicer's presets, which cover over a thousand printers, and choosing your printer gets all three. You don't need OrcaSlicer installed. deli setup does the steps below for you; this is what it does, and how to do more.

1. Find your printer

deli vendor                      # the vendors, with how many printers each
deli vendor Voron                # one vendor's printers
deli vendor "voron 2.4"          # or any part of a name: the printers that match

Orca's printer names end with the nozzle size, such as Voron 2.4 350 0.4 nozzle. Pick the one with the nozzle your printer has; most printers ship with 0.4 mm. Vendor names are Orca's folder names, so Bambu Lab's printers are under BBL; the list shows what a vendor's printers are called when it differs.

2. Choose it

deli printer "Voron 2.4 350 0.4 nozzle"

Any words of the name that are enough to tell it apart will do ("voron 350 0.4"), in any order and any case. A printer that is not in your library yet is imported from Orca as it is chosen, with the process and filament OrcaSlicer starts it with, and all three become the defaults for new prints. Every choice ends with the same block, what the print is now, with a note under anything that changed:

Imported printer 'voron-2.4-350-0.4-nozzle' from Orca 2.4.2's 'Voron 2.4 350 0.4 nozzle' (51 settings, 7 left out)
Imported process '0.20mm-standard-voron', Orca's default for this printer (94 settings, 16 left out)
  and made it the default process for new prints on 'voron-2.4-350-0.4-nozzle'
Imported filament 'generic-pla-system', Orca's default for this printer (27 settings, 20 left out)
  and made it the default filament for new prints on 'voron-2.4-350-0.4-nozzle'
Made 'voron-2.4-350-0.4-nozzle' your default printer for new prints
Printer   voron-2.4-350-0.4-nozzle  bed 350 x 350 mm, height 325 mm, nozzle 0.4 mm, firmware klipper
Filament  generic-pla-system  PLA, nozzle 220 °C, bed 55 °C
          from your config for this printer
Process   0.20mm-standard-voron  layers 0.2 mm, infill 15% cubic, perimeters 3
          from your config for this printer
Parts     none yet; add one with: deli add <file>
Sends to  nowhere yet; set with: deli config printers.voron-2.4-350-0.4-nozzle.host <moonraker://...|elegoo://...|octoprint://...>
Settings  none changed

deli status shows the block at any time.

You can slice now. The settings "left out" are ones PrusaSlicer's engine has no equivalent for; they need nothing from you. PRINTERS.md says which of Orca's printers deli has converted and sliced with, and why the rest fail. Slicing is not the same as printing well; see "Not done yet" for what has actually been printed.

Defaults are only filled in where you have none, so a second printer does not change your default printer, and a filament you chose yourself stays chosen. Once imported, a printer is in your library (~/.config/deli/), and choosing it again reads it from there: a newer deli or a newer Orca never changes a printer under you.

A filament or process belongs to a printer: it is how a material, or a layer height, prints on that machine's hotend and bed, which is why Orca keeps one per printer family and names them Generic PLA @System, Elegoo PLA @ECC. deli keeps each under the printer it was converted for, named without that tail: generic-pla under your Voron and elegoo-pla under your Centauri are two files, each what Orca says for its printer. deli filament lists the ones for the print's printer; choosing one another printer has converts it for this one.

3. Other filaments and processes

deli filament                              # the filaments for your printer, the one in use marked
deli filament "Generic PETG @System"       # choose one
deli process                               # the processes for your printer
deli process "0.15mm optimal"              # choose one

deli filament lists the filaments made for the print's printer (or your default one), with any you have used or loaded yourself, and marks the one in use and the default. deli process does the same for processes, and deli printer lists your printers first, each with its nozzles, then your printer's vendor's. It makes no difference whether one has been used before: choose any of them by name, or words of it, and deli fetches and converts it as needed, for your printer. Orca's Generic filaments (Generic PETG @System and so on) fit any printer; the list counts them. --default makes a choice what new prints start with instead of choosing it for this one.

deli import: more control

deli import orca printer|process|filament "<name>" converts one of Orca's presets without choosing it, and says more about the conversion: the notes on what deli did, and with -v every Orca setting left out. Run it again to replace a profile with a fresh conversion, after a deli upgrade that fixes the converter, say. --printer "<name>" converts a process or filament for another printer than the one it says it fits, --printer-only imports a printer without its defaults, --name stores it under another name and -o FILE writes the INI file instead.

Where the presets come from

deli reads Orca's presets from its GitHub repository at release 2.4.2, the release PRINTERS.md was made from. A release never changes, so what is fetched is kept in ~/.cache/deli/orca/ and read from there afterwards. Other sources:

  • deli import ... --ref main (or any tag) reads another version of Orca's presets, for printers newer than the release. Only releases are kept; main is fetched each time.
  • deli import ... --local reads the OrcaSlicer installed on this machine instead, including presets you have edited or created in Orca, which only exist there. --orca DIR adds a folder of Orca presets.

Listing every vendor makes one call to GitHub's API, which allows 60 an hour without signing in, and is then kept like the rest.

Without OrcaSlicer's presets

deli load takes a PrusaSlicer INI file from a path, a file:// URL or an https:// URL, including a link to a file's page on GitHub; --printer NAME says which printer a filament or process is for (default: the print's, else your default printer):

deli load printer  ~/Downloads/my-printer.ini --name my-printer   # a PrusaSlicer export, say
deli load filament https://example.com/profiles/my-petg.ini        # or a file someone hosts
deli printer my-printer                                            # then choose it as usual

Without --name, a profile is named as the file names it (PrusaSlicer's printer_settings_id and the like), and deli load says what that is.

A full PrusaSlicer export holds a printer, a process and a filament; deli load printer keeps only the printer's settings, so load it once for each. This repository's profiles/ has a few to try, converted from Orca's and checked to slice.

Anyone can host a printer this way: a PrusaSlicer INI file at any https:// address. Imported or loaded, a file never carries a printer's network address or API key; those go in your config (below).

Name your printer

Orca has a profile per nozzle, so its names are long and a nozzle change is another profile. deli lets you name the printer you have, and keep its nozzles under that name:

deli printer "voron 2.4 350 0.8" --name voron    # your Voron, with its 0.8 nozzle in
deli nozzle 0.4                                   # you changed the nozzle: Orca's 0.4 profile comes in
deli nozzle                                       # its nozzles, and which is in it
deli printer voron                                # this print goes on it, with whatever nozzle it has

The address, the settings you give it with deli set --printer voron, and deli send all go by the printer's name, whatever nozzle is in. Each nozzle keeps its own profile and the filament and process a new print starts with. deli setup names a printer after its host name. A printer you never named is one named after its profile, as before.

Tell deli where your printer is

To send prints to it, deli needs its address:

deli config printers.voron.host moonraker://voron.local

And to change what new prints start with:

deli printer voron --default                      # the printer new prints start with
deli filament "Generic PETG @System" --default     # the filament new prints on it start with, with this nozzle
deli process "0.15mm Optimal @Voron" --default     # its usual process, with this nozzle

This writes ~/.config/deli/config.toml, which you can also edit by hand. host is where deli send sends; its scheme says what kind of host the printer is: moonraker:// (Klipper), octoprint:// or elegoo:// (Elegoo's Centauri Carbon) (api_key alongside, if the host needs one). filament and process are what a new print on that printer starts with, kept per nozzle, so you do not choose them again for every print. They are defaults and nothing more: a print that chooses another filament is sliced and sent like any other.

The three --default lines write the config's printer key (deli config printer <name> sets the same one), and the filament and process of the nozzle the print is on (printers.<printer>.nozzles.<size>.filament, or printers.<printer>.filament for a printer named after its one profile). A print started in a new directory, with deli add say, takes all three, written into its deli.toml like any other choice. A print that wants something else chooses it with deli printer, deli filament or deli process as usual, and changing a default later leaves the prints you already have alone. deli printer lists your printers first and marks your default, and deli config shows everything that is set.

Print something

In a new directory:

deli add 3DBenchy.stl                 # STL, OBJ, 3MF or AMF; the print starts with your default printer, filament and process
deli add https://example.com/boat.zip # or fetched from the web: a model file, a zip of them, a page linking to them, or a Printables model (--file picks one of several)
deli printer "bambu p1s 0.4"          # another printer for this print, by any words of its name; its filament and process come with it
deli filament "generic petg"          # another filament than its default, converted for this printer
deli set infill 20%                   # or any PrusaSlicer setting by name
deli supports organic                 # automatic supports, for a model that needs them: on, off, grid, snug, organic
deli scale 150%                       # a bigger boat
deli scale z 60mm                     # or one side to a size, the others left as they are: z is up, however the part is turned
deli rotate 45                        # turned on the bed
deli mirror x                         # or its mirror image, for the other side of a pair
deli move 60 80                       # put it there instead of in the middle
deli pause 40                         # pause once layer 40 is done: change the filament for a two-colour boat
deli view                             # the Benchy on the bed in your browser, live; the shell stays free
deli slice                            # how long it takes, how much filament, and where it lies on the bed; the view then shows it layer by layer
deli send                             # uploads it, slicing first if needed; add --print to start printing
deli status                           # the print at a glance: printer, filament, process, parts, where it sends, settings, G-code

deli printer, deli filament, deli process and deli nozzle show the same block after a change, with a note under each row that changed: what it was, and why the filament or process followed the printer.

Several pairs go in one command, deli set infill_pattern rectilinear infill 100%, checked together, each against the print with the pairs before it applied, and written only when every one passes: a density only some patterns allow may follow its pattern, and a batch with a bad pair changes nothing.

deli set with nothing after it lists the settings this print changes, each with what its profile had, so the few things you changed are never lost among the hundreds you didn't. Settings that come from the printer, filament or process are not in that list; to look one up, give its name, and deli says where its value comes from:

$ deli set
fill_density = 20%  (the process '0.30mm-standard-elegoo-cc-0.6-nozzle' has 15%)
layer_height = 0.25  (the process '0.30mm-standard-elegoo-cc-0.6-nozzle' has 0.3)
$ deli set temperature
temperature is not changed by this print; the filament 'elegoo-pla-ecc' has 210
$ deli set fuzzy_skin
fuzzy_skin is not changed by this print; PrusaSlicer's default has none

deli unset layer_height goes back to the profile's value. Several settings go in one command, deli set infill 20% walls 3, and deli unset alone lists what there is to remove. When you know roughly what a setting is called, give that: deli set temp lists every setting with temp in its name, each with its value and where it comes from.

A value can come from a file, @ in front of its name, which is how to give G-code:

deli set --printer voron start_gcode @start.gcode
deli set start_gcode                                    # shows it as lines

deli keeps the text, not the file's name, written as lines in deli.toml or your config, so it reads and edits like G-code there:

[printers.voron.settings]
start_gcode = '''
M190 S{first_layer_bed_temperature[initial_extruder]}
M109 S[first_layer_temperature]
PRINT_START EXTRUDER=[first_layer_temperature] BED={first_layer_bed_temperature[initial_extruder]} MATERIAL=[filament_type]
'''

On the command line a line break is \n, as PrusaSlicer writes it. A filament's start and end G-code are one value per extruder in PrusaSlicer, ; between them; a value you give is one extruder's, comments and all, and several extruders' are written quoted as PrusaSlicer does ("..." ; "...").

A setting you want on every print, whichever printer, goes in your config instead of the print, with --global:

deli set --global infill 20%          # for every print, in ~/.config/deli/config.toml
deli set --global                     # list those
deli unset --global infill            # back to each print's profile

It lies under every print's own settings, which still win, so deli set infill 30% in one directory changes that print alone, and the listing says which is which. A global setting changes a print's G-code like any other change: deli send slices again first.

A printer that is not quite Orca's any more, after upgrades and modifications, keeps its differences the same way, under its name; so does a spool that prints best a little off its profile, or a process you always adjust:

deli set --printer voron max_print_height 310
deli set --printer voron start_gcode "..."
deli set --filament generic-pla temperature 215      # this print's printer's PLA (or your default printer's)
deli set --process "0.20mm Standard" walls 3
deli set --printer voron --filament generic-pla filament_max_volumetric_speed 30   # another printer's
deli set --printer voron                             # list a profile's

A filament's or process's settings are the printer's, as the filament itself is: the pressure advance and the volumetric cap that suit a material in one hotend are not right in another, so they are kept under the printer (printers.voron.filaments.generic-pla.settings). A hotend's own limit, the most it can melt whatever the material, is a different setting, max_volumetric_speed, and goes under the printer (deli set --printer voron max_volumetric_speed 30): the engine applies it beside the filament's, the lower winning. deli set --printer refuses the filament's cap, which there would silence every filament's own.

They go in your config beside Orca's profile, not into it, so every print with that profile has them, and a deli import of a newer Orca profile keeps them. This is deli's custom profile: Orca's base plus your changes. The layers, each winning over the one before: the chosen profiles; your global settings; the printer's; the filament's; the process's; the print's own. A name can be any part of it that only one profile in your library has.

A print can hold several models, each added the same way, and copies of one: deli add 3DBenchy.stl --count 4 prints four, arranged on the bed for you. With more than one model, scale, rotate, mirror and move take the model's name first (deli scale 3DBenchy 150%).

A model can come from the web: deli add <url> fetches it into the directory, adds it like any file, and records the address as the part's source in deli.toml. The address may be of the model file itself, of a zip holding model files, or of a page linking to them, such as a file's or a folder's page on GitHub; with several model files to choose from, deli lists them and --file NAME picks one. Adding the same address again adds a copy. A Printables model's page (printables.com/model/...) works too: the page itself only opens in a browser, but deli asks the site's API for the model's files and their links, which it hands out without a login. Other model sites do not have such a route: Thingiverse's pages and links refuse anything but a browser, and MakerWorld, Thangs, Cults3D and MyMiniFactory want an account before handing out a file. For those, download the file in your browser and deli add it; support for a site is added when it turns out to have a way in like Printables', one site at a time.

deli add given a Printables model's address lists its two files, fetches the one named with --file, then deli supports organic, deli slice and deli view

The G-code is kept in deli's cache (~/.cache/deli/gcode/), not beside deli.toml: deli send and deli view find it there, and deli send slices again by itself when the print has changed since. deli slice -o FILE (or -o DIR, -o . for here) also writes a copy where you want it, to put on an SD card or open in another program. After the time and filament, deli slice says where the print lies on the bed and how far it is from each edge, and prints as warning: lines anything PrusaSlicer's engine complained about while slicing (a tree support that lost a branch, say), each once.

Supports are PrusaSlicer's automatic ones. deli supports on uses the style the process came with (Orca's tuning for the printer carries over); organic, snug or grid pick one and turn them on; --angle 45 supports overhangs steeper than that, and --buildplate-only keeps them off the part itself. deli supports alone says what is in force and where it comes from. Underneath these are ordinary settings (support_material, support_material_style, ...), so deli set shows them and deli unset supports turns them off.

Parts are arranged on the bed for you, a single part in the middle. deli move 60 80 puts the middle of a part at x 60, y 80 instead, in millimetres from the bed's origin (the axes deli view draws). The first time something on a plate is moved, everything else on that plate keeps where it is, given a place of its own (deli move says so), so that moving one thing never moves another; moved parts and copies that would overlap are refused. deli move z -0.25 sinks a part a quarter of a millimetre into the bed, which is what a part resting on an edge or a lip needs to get a first layer; what is below the bed is not printed. deli move auto gives the placing back, and deli translate is the same command under another name. A part with copies is moved a copy at a time: deli move box --copy 2 60 80 places the second, and deli rotate box --copy 2 x 90 turns it alone (rotating the part turns every copy). deli arrange has every part and copy arranged again, as before any was moved; deli arrange --plate 2 only what was moved on plate 2, which stays there.

What does not fit on the bed goes on a second plate, and so on, as many as it takes, and deli slice writes a G-code file for each (stand-plate1.gcode, stand-plate2.gcode) and says what is on each and how long it takes. deli move box plate 2 keeps a part to plate 2, its place (deli move box 60 80) then on that plate, and deli move box --copy 3 plate 2 keeps only the third copy there; deli move box auto lets it go on the first plate it fits on again. A print that fits on one plate never mentions plates. deli send uploads every plate; deli send --plate 2 --print uploads plate 2 and starts it, since a printer prints one plate at a time.

deli pause 30 has the printer pause once layer 30 is done, to drop in a magnet or a nut, or to change the filament: deli has no separate colour-change command, because a pause is where you change it. What is written is the printer's own pause G-code (on many printers M600, the filament-change command itself; deli set pause_print_gcode changes it). Layers are counted as the slider in deli view counts them, so slide to the last layer you want printed before the pause and use that number. deli slice reports each pause with its height, and refuses a pause after a layer the print does not have. On a print with several plates, deli pause 30 --plate 2 pauses plate 2; without --plate a pause is the first plate's.

deli view opens a page in your browser and gives the shell straight back; the page follows the print as you change it. It shows the parts on the bed and, once deli slice has run and for as long as the G-code is still the print's, every extrusion in it, supports included, coloured by what it is for. The parts are then drawn faint over the extrusions, or hidden: Model in the legend shows or hides them, and they come up by themselves for the tools that need them. When the print has changed since it was sliced, or has never been, the page shows the parts and says so, with a Slice button that runs deli slice and shows what it printed. Sending stays in the shell. A print with several plates has a button for each, and the page shows one plate at a time.

The slider at the bottom goes through the layers, each with the time it takes, cutting the parts at the same height; a box shows only that layer. With no G-code it cuts the parts at a height instead, to show their inside. The colours turn lighter where the print pauses. The legend says how long each kind of extrusion takes, and travel; click one to hide or show it. "Colour by" colours the print by speed, flow (mm³/s) or layer time instead, from blue for the least to red for the most, which shows at a glance what is slow. The times are PrusaSlicer's estimate from reading the G-code back, as its own G-code viewer makes it, and can be a minute or two from the one deli slice reports. Overhangs shows in red the faces supports would hold up (at the print's support_material_threshold, or the angle PrusaSlicer works out when it is 0).

Click a part to select it, Shift-click to add another, or click a part's name in the box for every copy of it; a tool used on a selected part acts on the whole selection, one command per copy, and Remove gives the deli remove that takes the selection out. Click the empty bed, Clear or Esc to select nothing.

Dragging, Rotate, Lay flat and Mirror change the print with deli's own commands: drag a part over the bed for its deli move (a copy is moved by itself, with --copy; a drag that would put it off the bed or on another part offers nothing); with Rotate (or R) drag a part around to turn it on the bed, by 15°, or 1° with Shift, for its deli rotate ... z (and, for one not yet placed, the deli move that keeps it where it is); or with Lay flat click a face of one for the deli rotate that lays that face on the bed (that copy's only); with Mirror click a side of one for the deli mirror along that side's axis (a side for left to right, the top for top to bottom); Arrange, once something has been moved, gives deli arrange (--plate N for the plate shown, on a print of several); Pause here, beside the layer slider, does the same for deli pause at that layer. The page shows the command, and Apply runs it (Copy, to run it yourself); either way deli.toml changes as the command says and the page follows. Once the print is sliced, and deli knows the printer's address, Send and Print run deli send for the plate shown (Print, which starts the printer, asks once more). Only the page at the address deli view printed can apply commands. To measure, press Measure (or M) and click two points on the parts or the print: the line follows the pointer from the first, and the page shows the distance between them and along each axis, snapping to a corner of a part when you click near one. Esc clears; a right-click clears and puts the tool down. The mm / in switch, below the print's description, shows every length on the page (sizes, places, layer heights, measurements) in millimetres or inches; commands stay in millimetres. Supports, beside the tools, gives deli supports on or off.

The page is served in the background until it has been closed for ten minutes, or until deli view --stop. When the printer's profile asks for a thumbnail, deli slice draws one into the G-code for the printer's screen.

deli view in a browser: a sliced model with organic supports building up layer by layer, coloured by what each extrusion is for; the supports hidden and shown again from the legend; then one layer at a time with "only this layer"

deli printer, deli filament, deli process, deli set, deli supports, deli scale, deli rotate, deli mirror, deli move and deli pause without arguments show what is chosen. deli remove, deli unset, deli scale 100%, deli rotate 0, deli mirror off, deli move auto, deli arrange and deli pause off undo things. Everything is in deli.toml, which is plain TOML you can edit, comment and commit:

pause = [40]

[printer]
name = "voron-2.4-350-0.4-nozzle"
sha256 = "9510435c7c2100a23514b823aaab26fc37e9efe6a7e8031c1a2e03ecb687192c"

[[part]]
file = "3DBenchy.stl"
scale = [1.5, 1.5, 1.5]
rotate = [0, 0, 45]
at = [60, 80]

[settings]
fill_density = "20%"
support_material = 1
support_material_auto = 1
support_material_style = "organic"

The filament and the process have tables like the printer's. The hash records which version of the printer the print was set up with; if the printer in your library changes, deli slice says so and deli printer <name> accepts the new version.

Before a first real print: deli send without --print only uploads, so you can check the file arrived and start it from the printer's own screen.

Commands

deli setup [--printer NAME] [--host ADDRESS] [--shell bash|zsh|fish] [--no-completion] tab completion, your printer and its address, asked for once; the options answer the questions in advance
deli printer|filament|process [name] choose one for this print, by its name or any words of it, from your library or else OrcaSlicer's (imported as it is chosen, under Orca's name or --name NAME; a printer brings its default process and filament), or list your library's; --default makes it the default for new prints instead
deli status [--json] the print at a glance: printer, filament, process, parts, where it sends, settings changed, G-code and its file; and, looked up once a day, whether a newer deli is out (deli config update_check false stops that). --json gives the same as data
deli nozzle [size] the nozzles of this print's printer, or put one in: its profile comes from Orca if need be, and the print moves to it
deli vendor [vendor|printer] list printer vendors, a vendor's printers, or the printers a name is part of
deli import orca <kind> "<name>" convert an OrcaSlicer preset into your library without choosing it
deli load <kind> <source> [--name NAME] [--printer NAME] copy a PrusaSlicer INI file into your library, under its own name or --name; a filament or process under the printer it is for
deli add <file|url> [--count N] [--file NAME] add a model, or more copies of it; a URL is fetched here first, --file choosing among several in an archive, on a page or in a Printables model
deli remove <part> [--count N|--copy N] take a part out, or its last N copies, or one copy by its number
deli set [setting] [value] / deli unset change, show or list this print's settings; several pairs at once, checked together and written only when every one passes; --global, --printer NAME, --filament NAME or --process NAME for every print's with that profile, in your config; @FILE reads a value, G-code say, from a file, @- from standard input
deli supports [on|off|organic|snug|grid] automatic supports; --angle N, --buildplate-only or --everywhere
deli scale [part] [x|y|z] <factor> 110%, 1.1, or 30mm with an axis; the axis is the bed's, as the part lies once rotated
deli rotate [part] [x|y|z] <degrees> about z when no axis is given
deli mirror [part] [x|y|z|off] the part's mirror image along the bed's axis, as it lies once rotated; the same axis again, or off, puts it back
deli move [part] [--copy N] <x> <y> where the part's middle goes on the bed, or one copy's; z -0.25 sinks it, plate 2 keeps it to plate 2, auto has it arranged again. deli translate is the same command
deli arrange [--plate N] arrange every part and copy again, or one plate's, forgetting where they were moved
deli pause [off] [layer ...] [--plate N] pause after a layer, counted as the slider in deli view counts them; also how to change filament mid-print
deli slice [-o FILE|DIR] [--json] slice, and say how long it takes, how much filament, where it lies on the bed and how far from the edges; -o writes a copy of the G-code, --json gives the figures as data. Parts that do not fit go on further plates, a file each
deli view [--port N] [--no-browser] [--stop] the parts on the bed in your browser; after deli slice, the sliced print with its supports, layer by layer. Served in the background until the page has been closed for ten minutes, or --stop; --no-browser prints the address instead of opening one
deli send [FILE] [--print] [--level] [--plate N] [--name NAME] upload to the printer in your config, slicing first if the print has changed; every plate, or --plate N; --name for what to call it there; --level with --print has an Elegoo printer level its bed first. A printer that is printing is said to be, not sent to; exit code 3 when it cannot be reached, 4 when it is busy
deli config [key] [value] [--unset KEY] your default printer, your printers' addresses and default filament and process, and the settings for every print and for each profile; --unset removes a key
deli completion bash|zsh|fish shell completion
deli update [version] [--check] install the latest release from GitHub over this one, or say whether there is one

deli <command> --help has the details.

Using deli from an AI assistant

deli is a good fit for a coding assistant that runs shell commands: every command takes its arguments on the command line, prints plain text and exits (deli status --json and deli slice --json give the same as data), and a print is a file the assistant can read. The repository ships a skill, a short briefing in skills/deli/SKILL.md, that tells an assistant how deli thinks, the usual workflow, the rules it should keep (never deli send --print unless asked; never deli setup, which asks questions) and where the settings are. It follows the Agent Skills format, so it works with Claude Code, Codex, OpenCode, Pi and the other tools that read SKILL.md files. To install it for yours:

npx skills add dcruver/deli-slicer          # into whichever agents you have

or copy skills/deli/ into the folder your tool reads skills from (~/.claude/skills/, ~/.codex/skills/, ~/.config/opencode/skills/, ...). Within this checkout, Claude Code finds it through .claude/skills/deli.

Not done yet

Things that a user would notice, roughly in the order they matter:

  • Two printers have printed deli's G-code so far: an Elegoo Centauri Carbon and a Voron 2.4 running Klipper, both with profiles converted from Orca's and the files sent with deli send --print (to the Centauri, and to Moonraker). On the Centauri, a cube in PLA printed well; a Benchy in PETG-CF stopped at its deli pause, parked the head, carried on when resumed and ran to the end, but came out stringy, from a spool that was probably damp. On the Voron, a Benchy in PLA and a two-part desiccant canister in PETG with a 0.8 mm nozzle printed cleanly (the canister's thread, designed for a 0.4, did not survive the nozzle, which is no slicer's fault). One print with organic supports, a phone stand on the Centauri, came out rough where the supports touched it and on overhangs left unsupported; converted profiles give overhangs no extra fan yet (PLAN.md). deli send to OctoPrint has only been tested against a fake. If you print with another printer, please say how it went (see CONTRIBUTING.md).
  • Converted profiles differ from Orca in small ways. The first layer's layer-change G-code is skipped; one bridge speed instead of two; no brim where Orca would add one automatically. PLAN.md has the full list with measurements.
  • What printers' screens show is barely checked. The G-code carries the M73 remaining-time lines and, for converted printers, the comment lines Orca's files end with (the profile's gcode_footer), where some firmware reads the layer count. The Centauri Carbon shows the layer count; its remaining time has not been watched yet.
  • Other printers. Of the 1,001 printers OrcaSlicer 2.4.2 ships, 789 convert and slice a test cube; PRINTERS.md lists every one, and why the rest fail. Only the Centauri Carbon and the Bambu Lab P1S have been compared with Orca's own output.
  • Bambu printers can't be sent to. deli send does not speak Bambu's LAN or cloud protocols; write the G-code out with deli slice -o . and copy it over by hand (SD card, or another program's send).
  • No Windows wheel. On Windows, deli runs in WSL (above); a wheel of its own needs deli view's background server ported first.
  • Settings apply to the whole print, not to one part.
  • Supports are PrusaSlicer's automatic ones; painted supports need a 3MF painted elsewhere, which is untested.
  • One filament per print. A change by hand at a deli pause is the only kind; filament-change G-code for multi-material printers is not converted.
  • No STEP files. PrusaSlicer reads them through a library deli does not ship.
  • Only Printables among the model sites. deli add <url> takes any address that serves a model file, a zip or a page linking to files, and Printables through its API. Thingiverse needs a browser, and MakerWorld, Thangs, Cults3D and MyMiniFactory an account; a site is added when it has a way in without one.
  • Hosts: PrusaLink, Duet and the others PrusaSlicer knows are not supported by deli send; the Centauri Carbon 2's newer protocol is not either.

Engine

PrusaSlicer 2.9.6's source is vendored as a git submodule at vendor/PrusaSlicer. deli links its libslic3r into a Python extension module; nothing of PrusaSlicer's GUI is built. PLAN.md has the build details and the project's current state.

Contributing

DESIGN.md says how deli is meant to work and why; CONTRIBUTING.md says how to build it, test it and send a change, and what help is most wanted (printing with a printer that has not printed deli's G-code yet, above all). CHANGELOG.md lists what changed in each release.

License

AGPL-3.0-only, the same licence as the PrusaSlicer code it links. See LICENSE. The profiles in profiles/ are derived from OrcaSlicer's, which are AGPL-3.0 too. The libraries compiled into deli's wheels, and the three.js the viewer bundles, are listed with their licences in THIRD-PARTY-NOTICES.md.

Metadata

Release files for deli-slicer 0.17.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Built distributions (wheels)

Table of built distributions (wheels) for deli-slicer 0.17.0
File
deli_slicer-0.17.0-cp312-abi3-manylinux_2_28_x86_64.whl CPython 3.12 abi3 Linux glibc 2.28+ x86-64 Details
deli_slicer-0.17.0-cp312-abi3-manylinux_2_28_aarch64.whl CPython 3.12 abi3 Linux glibc 2.28+ ARM64 Details
deli_slicer-0.17.0-cp312-abi3-macosx_11_0_arm64.whl CPython 3.12 abi3 macOS 11.0+ ARM64 Details
deli_slicer-0.17.0-cp312-abi3-macosx_10_15_x86_64.whl CPython 3.12 abi3 macOS 10.15+ x86-64 Details

Total release size: 84.3 MB

Release files / deli_slicer-0.17.0-cp312-abi3-manylinux_2_28_x86_64.whl

Download URL deli_slicer-0.17.0-cp312-abi3-manylinux_2_28_x86_64.whl
Size 25.2 MB
Tags CPython 3.12 Linux glibc 2.28+ x86-64 abi3
SHA-256 checksum
How to use checksums
01303d190ccae47186bf6492099899061aa10fc23340761f0b14aebea603d7b0
BLAKE2b-256 checksum
How to use checksums
8213841eed53060f908f111bbc7267b6d86970370c0bde662861aa6fb4460451
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.

Transparency log

Release files / deli_slicer-0.17.0-cp312-abi3-manylinux_2_28_aarch64.whl

Download URL deli_slicer-0.17.0-cp312-abi3-manylinux_2_28_aarch64.whl
Size 23.5 MB
Tags CPython 3.12 Linux glibc 2.28+ ARM64 abi3
SHA-256 checksum
How to use checksums
3bd4b90a00ebe13facd92f3c01df68025c024750d40c59dc95f0020818acf0ef
BLAKE2b-256 checksum
How to use checksums
f6a75059110ba2a6473f2a6925eb695a4f6b6d31ae8af18c19fd2539cc5d7dde
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.

Transparency log

Release files / deli_slicer-0.17.0-cp312-abi3-macosx_11_0_arm64.whl

Download URL deli_slicer-0.17.0-cp312-abi3-macosx_11_0_arm64.whl
Size 16.8 MB
Tags CPython 3.12 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
d849cdbbbae1b5e7fccf3bb42943cbe0e9c9744e3594f9f218a9586bb4b3aaa8
BLAKE2b-256 checksum
How to use checksums
4b7efd0aa1caf4a22688431fda770b9add1939cf6ca5355c29860e8e2669479f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.

Transparency log

Release files / deli_slicer-0.17.0-cp312-abi3-macosx_10_15_x86_64.whl

Download URL deli_slicer-0.17.0-cp312-abi3-macosx_10_15_x86_64.whl
Size 18.9 MB
Tags CPython 3.12 abi3 macOS 10.15+ x86-64
SHA-256 checksum
How to use checksums
ecdae671e7f88812352c0bf95e9475fc4e2080215e0612bf1fc0e7928239e6e8
BLAKE2b-256 checksum
How to use checksums
1f3cc52da6bb6109a44b76ecf610cc118dec59926aabe9cda025f0b9b4e0b118
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.

Transparency log

Security for deli-slicer 0.17.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 4 files in this release have been uploaded with provenance metadata.

Select from 4 files

Attestation for deli_slicer-0.17.0-cp312-abi3-manylinux_2_28_x86_64.whl

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page