# MIDILLI STL Generator for 3D Printers

Aa free and versatile command-line tool for creating STL files to prepare box-shaped parts with the help of free and open-source OpenSCAD.

# Introduction

**MIDILLI STL Generator** is a free and versatile command-line tool for creating [STL](https://en.wikipedia.org/wiki/STL_(file_format)) files to prepare box-shaped parts with the help of free and open-source [OpenSCAD](https://openscad.org/). It supports circular drill holes, rectangular cutouts, text engraving, and precise dimensions in metric units. The generated STL files can be opened in 3D viewers, or can directly be used in [slicers](https://en.wikipedia.org/wiki/Slicer_(3D_printing)) to be printed via 3D Printers.

![image.png](https://docs.midilli.tech/uploads/images/gallery/2025-11/scaled-1680-/R0fimage.png)*MyPart\_Top.stl: Separated top with components of the example project.*

<div class="wp-block-group" id="bkmrk-"><div class="wp-block-columns"></div></div>![image.png](https://docs.midilli.tech/uploads/images/gallery/2025-11/scaled-1680-/Mcyimage.png)*Other five sides of the example project with screw holes visible.*

Derived from the in-house MIDILLI Tech Automation Suite, this tool is a simplified yet robust solution.

It is offered free for non-commercial use. You can find the full license details [here](https://midilli.tech/software-license/).

<p class="callout danger">Warning: Operating 3D printers requires a safe environment to prevent exposure to hot surfaces, moving parts, and emitted fumes. Never place your hands near the moving parts or the print head. Always ensure proper ventilation, wear safety goggles, and use hearing protection if necessary. Additionally, perform a simulation to ensure the print job does not attempt to print in restricted or potentially dangerous areas.</p>

Please choose a topic from left to read.

# Features

- **Box Creation**: 
    - Generate rectangular shapes with up to six sides to form a complete box structures.
    - Option to omit or separate any side during box design.
    - Option to use the sizing for the inner volume or the outer volume.
- **Customizable Cutouts**: 
    - Create holes or rectangular cutouts (also called components) on specific sides of the box with precise locations.
    - Create screw holes on top or bottom side with the given screw diameter.
- **Component Rotation**: 
    - Rotate components to any specified angle in degrees.
- **Text Engraving:**
    - Create text engravings with adjustable font sizes, rotation (aligned with component rotation), and customizable engraving depth.
- **Recess Support:**
    - Create flush surfaces with custom dimensions that prevent movement of e.g., button caps and improve functionality.
    - Create recesses for screw heads<sup>\*</sup>.
- **Single or Multiple Sides:**
    - Separate sides of the box, or create as a single part.
- **Material Thickness**: 
    - Adjust material thickness for accurate cuts and fits.
- **Box Sizing**: 
    - Automatically adjust box sizes for inner or outer edges, depending on user preference.
- Create OpenSCAD projects to enable fine-tuning.

# How does it work?

The tool takes a JSON file as input (example below) and generates STL files for up to six sides of a box, with each side containing its own drill cutouts, and recesses. These pieces can then be assembled to construct a 3D shape, or a single part can be generated.

The exported [*.stl files*](https://en.wikipedia.org/wiki/Numerical_control) must be used with a slicer software (or a 3D Printer software) to complete the task.

# Download

By downloading our free software, you agree to the [license conditions](https://midilli.tech/software-license/).

[Download (Windows, Linux, macOS)](https://midilli.tech/product/midilli-stl-generator-for-3d-printers/)

# Version History

- 1.3.0 (27.08.2026): 
    - Added finger joint support with `--finger-joint` and per-side `--no-finger-*` options.
- 1.2.0 (05.11.2025): 
    - Now available for Windows, Linux, and macOS as well.
    - `box-height-3d`, `material-thickness` and `outer-sizing` arguments can be also used in JSON (can be overridden via command-line argument)
- 1.1.1 (15.07.2025): 
    - Added option to separate any sides from the merged file, if used with `--single-part`.
- 1.1.0 (01.04.2025): 
    - Added text engraving option with custom rotation, font size, and engraving depth.
- 1.0.1 (08.02.2025): 
    - Replaced `height` with `length` in JSON to avoid confusion.
- 1.0.0 (22.01.2025): 
    - Initial version.

# Quick Usage

### Introduction

Download the ZIP file and extract to a location. Copy the *Example JSON file* below and save it as *test.json* using a simple text editor. To keep the things simple, save it at the same location as the executable.

To create your own JSON file, use our online [visual box designer](https://midilli.tech/visual-box-designer/) or [JSON Creator](https://midilli.tech/midilli-tools-json-creator/) or refer to [MIDILLI JSON Definition](https://midilli.tech/help-and-support/manuals/manuals-free-tools/midilli-json-file-definition/) document to create your own from scratch.

### Example JSON file

The following file generates all six sides for *MyPart*, placing one hole and one rectangle cutout on the *Top* side. The top size of the box is 5x5 cm and the components are placed at (x = 1, y = 1) and (x = 3, y = 3) respectively. The visible sizes of the components are the same as drill sizes.

```
{
	"Generic": {
		"width": 5.0,
		"length": 5.0
	},
	"MyPart_Top": {
		"myRoundComponent#1": {
			"location_x": 1,
			"location_y": 1,
			"drill_diameter": 1,
			"call_name": "Hello",
            "visible_diameter": 1,
			"rotation": 0
		},
		"myRectangleComponent#1": {
			"location_x": 3,
			"location_y": 3,
			"drill_width": 2,
			"drill_length": 1,
			"call_name": "MIDILLI",
			"visible_width" : 2,
			"visible_length" : 1,
			"rotation": 0
		}
	},
	"MyPart_Bottom": {

	},
	"MyPart_Back": {
		
	},
	"MyPart_Front": {

	},
	"MyPart_Left": {

	},
	"MyPart_Right": {

	}
}
```

Depending on the command-line options, the other sides of the part will be created using different sizing. Read *Coordinate system* *and effect of sizing parameters* for more on different results of the arguments.

<p class="callout info">**Note**: JSON syntax is very strict. Ensure that the last line before each '}' does **not** end with a comma, while all other lines **should**. Use an online validation tool to confirm correctness.  
</p>

<p class="callout info">**Note**: Use dot (.) if working with decimal numbers to separate the integer part.</p>

### Command line

Assuming that the JSON file is stored at the same location as the executable file, open a command window (Command Prompt, or PowerShell), then execute the following command:

**Note: The following command requires installation of the free and open-source [OpenSCAD](https://openscad.org/downloads.html) software.**

```
.\STLGenerator.exe --json-file .\test.json --output-directory .
 --material-thickness 3 --box-height-3d 30 --single-part --separate-top
```

You will be provided with an output showing the current settings as following:

```
~~~~~ Settings ~~~~~
Single part: Yes
Separate top: Yes
Separate bottom: No
Separate back: No
Separate front: No
Separate left: No
Separate right: No
Screw diameter: 0 mm
Screw head height: 0 mm
Screw head diameter: 0 mm
Screw extra margin: 0 mm
Outer sizing enabled: No (from JSON)
Finger joints: No
Finger size: 3 mm (default: material thickness)
Finger count: Automatic
Finger clearance: 0 mm
Outer sizing enabled: No
Material thickness: 3 mm
Box height in 3D: 30 mm
Recess depth: 0 mm
Draw text: Yes
Font size: 8 px
Text depth: 1 mm
OpenSCAD path: C:\\Progra~1\\OpenSCAD\\openscad.exe
Keep OpenSCAD files at the end: No
Create only OpenSCAD files: No
Verbose enabled: No
```

Each setting on the console output can be customized with command line arguments.

**Note**: Use dot (.) if working with decimal numbers to separate the integer part.

After completion, 6 files starting with *MyPart\_* and ending with *.stl*, *test\_merged.stl*, and *MyPart\_Top.scad* file will be visible under *test* directory. Opening *MyPart\_Top.stl* and *test\_merged.stl* in a program which can view STL files should display results similar to the following:

[![image.png](https://docs.midilli.tech/uploads/images/gallery/2025-12/scaled-1680-/image.png)](https://docs.midilli.tech/uploads/images/gallery/2025-12/image.png)  
MyPart\_Top.stl: Separated top with components of the example project.

<div class="wp-block-columns are-vertically-aligned-top" id="bkmrk-test_merged.stl%3A-res"><div class="wp-block-column is-vertically-aligned-top">  
</div><div class="wp-block-column is-vertically-aligned-top"> ![](https://midilli.tech/wp-content/uploads/2025/01/test-stl-separated-top-singlepart.png)  
test_merged.stl: Rest of the sides are combined as a single part.</div></div>From this point, you can use your slicer software to start printing.

<details id="bkmrk-hint-tip%3A-if-you-wan"><summary>Hint</summary>

Tip: If you want the overall size to be exactly as you specify in the JSON file, use the --outer-sizing option. If you want the usable inner area to be the same as you define, leave it as default.

</details>

# Coordinate system and effects of sizing parameters

Read more on the following page: [Understanding 2D Coordinate Systems in MIDILLI Tools](https://docs.midilli.tech/books/reference-documents/page/understanding-2d-coordinate-systems-in-midilli-tools "Understanding 2D Coordinate Systems in MIDILLI Tools")

# Command line arguments

#### Introduction

If the program is executed with `-h` or `--help` option, the following quick help will be displayed:

```
Usage:
  STLGenerator.exe [OPTION...]

  -j, --json-file arg           Project JSON file
  -o, --output-directory arg    Output directory
  -t, --material-thickness arg  Material thickness in mm (default: 0)
  -b, --box-height-3d arg       Box height in 3D in mm (default: 0)
  -s, --single-part             Merge all STL files to construct a 3D box.
                                Use --separate-top and/or --separate-bottom
                                to separate the sides
  -p, --separate-top            Do not combine the top side with the other
                                sides when using the --single-part option
  -m, --separate-bottom         Do not combine the bottom side with the
                                other sides when using the --single-part
                                option
  -y, --separate-back           Do not combine the back side with the other
                                sides when using the --single-part option
  -u, --separate-front          Do not combine the front side with the
                                other sides when using the --single-part
                                option
  -l, --separate-left           Do not combine the left side with the other
                                sides when using the --single-part option
  -g, --separate-right          Do not combine the right side with the
                                other sides when using the --single-part
                                option
  -w, --screw-size arg          Screw diameter in mm (default: 0)
  -d, --screw-head-height arg   Screw head height in mm (default: 0)
  -a, --screw-head-diameter arg
                                Screw head diameter in mm (default: 0)
  -e, --screw-extra-margin arg  Screw extra margin in mm (default: 0)
  -z, --outer-sizing            Box sizes are for outside borders (inner
                                area will be smaller)
      --finger-joint            Add finger joints (box joints) to the side
                                panels so they can be assembled without
                                glue. When enabled all 6 sides default on;
                                use --no-finger-<side> to disable a specific
                                side
      --finger-size arg         Finger width in mm (0 = material thickness)
                                (default: 0)
      --finger-count arg        Number of fingers on an edge (0 = automatic
                                from finger size) (default: 0)
      --finger-clearance arg    Extra clearance added to finger slots in mm
                                (default: 0)
      --no-finger-top           Disable finger joints on the top edge
      --no-finger-bottom        Disable finger joints on the bottom edge
      --no-finger-front         Disable finger joints on the front edge
      --no-finger-back          Disable finger joints on the back edge
      --no-finger-left          Disable finger joints on the left edge
      --no-finger-right         Disable finger joints on the right edge
  -r, --recess-depth arg        The depth of recess in mm (0 = no recess)
                                (default: 0)
  -x, --draw-text               Whether to draw text (default: true)
  -f, --font-size arg           Font size to draw in px (default: 8)
  -q, --text-depth arg          Depth to engrave text in mm (default: 1)
  -c, --openscad-path arg       Path to OpenSCAD executable (default:
                                C:\\Progra~1\\OpenSCAD\\openscad.exe)
  -k, --keep-project-files      Do not delete OpenSCAD files at the end
  -n, --only-project            Create only OpenSCAD files, do not create
                                STL files
  -v, --verbose                 Verbose output
  -h, --help                    Print this help and exit
```

<div class="wp-block-syntaxhighlighter-code" id="bkmrk-"><div><div class="syntaxhighlighter nogutter plain" id="bkmrk-stlgenerator.exe-%5Bop-1"></div></div></div>Both short and long versions of the arguments can be used.

The arguments `--json-file`, `--output-directory`, `--material-thickness`, and `--box-height-3d` are mandatory. The last two arguments can also be given in the JSON file. If both JSON and the command-line has these arguments, the command line values will be used. Other arguments have default values as mentioned above. To set an argument to false, use the long version and assign the value `false`. For example, to disable outline cut, use `--only-project=false`. Similarly, for verbose, use either `-v` or `--verbose`. Argument values can be provided with a space or an equal sign if long versions are used. For instance, both `--json-file test.json` and `--json-file=test.json` are valid usage. For short versions, only space allowed, e.g., `-b 30`.

#### `--json-file`

A valid path to JSON file to be used as input. Can be a relative path (starting from the working directory) or an absolute path. You can use online [visual box designer](https://midilli.tech/visual-box-designer), [JSON Creator](https://midilli.tech/midilli-tools-json-creator/) or refer to [MIDILLI JSON Definition](https://midilli.tech/help-and-support/manuals/manuals-free-tools/midilli-json-file-definition/) document if you need help.


#### `--output-directory`

The directory to write the output files to. Using `.` (dot) will use the current working directory. The final files will be written into a new folder having the name of the `--json-file`.

#### `--material-thickness`

This value is used to calculate the depth required for creating holes for components and/or screws. The value is in millimeters (mm).

Additionally, this value is used to determine the dimensions of the left, right, front, and bottom sides (if enabled) based on whether the `--outer-sizing` parameter is active. See *Coordinate system and effects of sizing parameters* for more info.

This value is mandatory.  
It can be given in the JSON (under Generic, as value “`material_thickness`“) as well as in the command line. Command line will override the value if provided.

#### `--box-height-3d`

The height of the box in millimeters (mm). If `--outer-sizing` is used, this will be the outer height of the box. Otherwise, it is the inner height of the box.

This value is mandatory.  
It can be given in the JSON (under Generic, as value “`box_height_3d`“) as well as in the command line. Command line will override the value if provided.

#### `--single-part`

Merges all sides into a single file (`.scad` or `.stl`) to construct a complete 3D box. To separate top or bottom, use `--separate-top` and/or `--separate-bottom` respectively.

Default: false

#### `--separate-top`

Separate top side of the box from the rest of the sides and save it as a separate file if `--single-part` option is used. This will also leave the `_Top.scad` project file in the folder.

#### `--separate-bottom`

Separate bottom side of the box from the rest of the sides and save it as a separate file if `--single-part` option is used. This will also leave the `_Bottom.scad` project file in the folder.

#### `--separate-back`

Separate back side of the box from the rest of the sides and save it as a separate file if `--single-part` option is used. This will also leave the `_Back.scad` project file in the folder.

#### `--separate-front`

Separate front side of the box from the rest of the sides and save it as a separate file if `--single-part` option is used. This will also leave the `_Front.scad` project file in the folder.

#### `--separate-left`

Separate left side of the box from the rest of the sides and save it as a separate file if `--single-part` option is used. This will also leave the `_Left.scad` project file in the folder.

#### `--separate-right`

Separate right side of the box from the rest of the sides and save it as a separate file if `--single-part` option is used. This will also leave the `_Right.scad` project file in the folder.

#### `--screw-size`

Screw hole diameter to be drawn as hole in millimeters (mm) on the top and/or bottom side of the box. Needs at least `--separate-top` or `--separate-bottom` to be used. Otherwise no screw holes will be generated.

This will also generate 4 cylindrical supports to fix the screws.

<div class="wp-block-image" id="bkmrk-cylindrical-supports"><figure class="aligncenter size-medium">![](https://mlg8ybik0dvi.i.optimole.com/w:300/h:300/q:mauto/dpr:1.3/f:best/ig:avif/https://midilli.tech/wp-content/uploads/2025/02/image-300x300.png)<figcaption class="wp-element-caption">Cylindrical supports will be created if <code>&#45;&#45;screw&#45;size</code> is set to a value.</figcaption></figure></div>Default: 0 mm, no screws.

<div class="wp-block-image" id="bkmrk-brown%3A-screw-diamete"><figure class="aligncenter size-full is-resized">![](https://mlg8ybik0dvi.i.optimole.com/w:159/h:151/q:mauto/dpr:1.3/f:best/ig:avif/https://midilli.tech/wp-content/uploads/2025/01/screw-parameters-screw-d.png)<figcaption class="wp-element-caption">Brown: Screw diameter (or screw size)</figcaption></figure></div>#### <code>&#45;&#45;screw&#45;head&#45;height</code>

The depth of the screw-head to create [counterbore/recessed](https://en.wikipedia.org/wiki/Counterbore) screws given in millimeters (mm).

Default: 0 mm, protruding screw head.

<div class="wp-block-image" id="bkmrk-gray%3A-screw-head-hei"><figure class="aligncenter size-full is-resized">![](https://mlg8ybik0dvi.i.optimole.com/w:159/h:151/q:mauto/dpr:1.3/f:best/ig:avif/https://midilli.tech/wp-content/uploads/2025/01/screw-parameters-hheight.png)<figcaption class="wp-element-caption">Gray: Screw head height</figcaption></figure></div>#### <code>&#45;&#45;screw&#45;head&#45;diameter</code>

If the screws must be [counterbore/recessed](https://en.wikipedia.org/wiki/Counterbore), any value given in millimeters (mm) (preferably greater than `--screw-size`) will create a circular shape to bury the head.

Default: 0 mm, protruding screw head.

<div class="wp-block-image" id="bkmrk-red%3A-screw-head-diam"><figure class="aligncenter size-full is-resized">![](https://mlg8ybik0dvi.i.optimole.com/w:159/h:151/q:mauto/dpr:1.3/f:best/ig:avif/https://midilli.tech/wp-content/uploads/2025/01/screw-parameters-head-d.png)<figcaption class="wp-element-caption">Red: Screw head diameter</figcaption></figure></div>The images below show how <code>&#45;&#45;screw&#45;head&#45;diameter</code> and <code>&#45;&#45;screw&#45;head&#45;height</code> affect the creation of screw head related recesses.

<div class="wp-block-image" id="bkmrk--1"><figure class="aligncenter size-full is-resized">![](https://mlg8ybik0dvi.i.optimole.com/w:359/h:197/q:mauto/dpr:1.3/f:best/ig:avif/https://midilli.tech/wp-content/uploads/2025/01/screws-prodtruding-counterbore.png)</figure></div>#### <code>&#45;&#45;screw&#45;extra&#45;margin</code>

By default, screws are added at the four corners of the top and/or bottom side of the box, leaving a margin of `--material-thickness` from the sides. If an additional margin is desired, any value given in millimeters (mm) will increase this gap.

Default: 0 mm, no additional margin.

<div class="wp-block-image" id="bkmrk-green%3A-screw-extra-m"><figure class="aligncenter size-full is-resized">![](https://mlg8ybik0dvi.i.optimole.com/w:159/h:151/q:mauto/dpr:1.3/f:best/ig:avif/https://midilli.tech/wp-content/uploads/2025/01/screw-parameters-margin.png)<figcaption class="wp-element-caption">Green: Screw extra margin</figcaption></figure></div>#### <code>&#45;&#45;outer&#45;sizing</code>

If used, the sizes defined in the JSON file as well as the `--material-thickness` and `--box-height-3d` arguments will be used to create the outer volume with the given dimensions. Otherwise, these values will be used to create the inner volume with the given dimensions.

The value can be given in the JSON (under Generic, as value “`outer_sizing`“) as well as in the command line. Command line will override the value if provided.

Default: false, use inner dimensions.

#### `--recess-depth`

The depth of the recess for components in millimeters (mm).

Recesses also take the sizing from *visible\_diameter* (priority) or *visible\_width* and *visible\_height* properties. Recesses may be helpful to have slightly lowered shapes to e.g., stabilize or limit the movement of button caps. This value does not change the behavior of the screw head recess (See `--screw-head-height`).

Default: 0 mm, no recess for the components

#### `--draw-text`

Whether to draw texts defined in the JSON file with `call_name`. Font size can be specified with `silkscreen_font_size` or with `--font-size` argument.

Default: true, draw text.

#### `--font-size`

The size of the font in pixels (px). The value is converted to OpenSCAD size value using the formula in its [manual](https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Text). This is only effective, if no `silkscreen_font_size` found for a `call_name`.

Default: 8 px.

#### `--text-depth`

The engraving depth for the text in millimeters (mm). If greater than `material-thickness`, `material-thickness` will be used. This value is used for all `call_name`s.

Default: 1 mm.

#### `--finger-joint`

Enables finger joints (box joints) on all 6 sides of the box so panels can be assembled without glue. By default, all 6 sides are enabled. To disable finger joints on specific sides, use the &#96;--no-finger-&lt;side&gt;&#96; arguments.

Default: false, no finger joints.

#### `--finger-size`

The width of each finger in millimeters (mm). If set to 0, the &#96;--material-thickness&#96; value will be used as the finger width.

Default: 0 mm (uses material thickness).

#### `--finger-count`

The number of fingers on an edge. If set to 0, the number of fingers will be calculated automatically based on the &#96;--finger-size&#96; value and the panel dimensions.

Default: 0 (automatic).

#### `--finger-clearance`

Extra clearance added to finger slots in millimeters (mm) to ensure smooth assembly.

Default: 0 mm.

#### `--no-finger-*`

Disable finger joints per side.

When `--finger-joint` is enabled, all 6 sides have finger joints by default. Use the following arguments to disable finger joints on specific sides:

- `--no-finger-top` — Disables finger joints on the Top panel
- `--no-finger-bottom` — Disables finger joints on the Bottom panel
- `--no-finger-front` — Disables finger joints on the Front panel
- `--no-finger-back` — Disables finger joints on the Back panel
- `--no-finger-left` — Disables finger joints on the Left panel
- `--no-finger-right` — Disables finger joints on the Right panel

#### `--openscad-path`

Path to OpenSCAD executable to convert `.scad` files to `.stl` files. Requires free and open-source [OpenSCAD](https://openscad.org/downloads.html) to be installed separately.

Default: C:\\Program Files\\OpenSCAD\\openscad.exe

#### `--keep-project-files`

Keeps the OpenSCAD files (`.scad` files) after conversion to STL.

Default: false, remove `.scad` files after conversion to STL.

#### `--only-project`

Only creates `.scad` files and does not start STL conversion. This is useful e.g., to work on the files using OpenSCAD for fine-tuning or modifications.

#### `--verbose`

Shows more information during project creation and outputs of the OpenSCAD software during STL conversion.

#### `--help`

Shows the quick help with the list of arguments and their short descriptions.

# JSON File

See the definition on this page: [MIDILLI JSON File Definition](https://docs.midilli.tech/books/reference-documents/page/json-file-definition).

# Additional Resources

- [Understanding Tool Diameter and Shape, Laser Kerf, and Nozzle Width in CNC, Laser, and 3D Printing](https://midilli.tech/understanding-tool-diameter-and-shape-laser-kerf-and-nozzle-width-in-cnc-laser-and-3d-printing/)
- [JSON File Definition](https://docs.midilli.tech/books/reference-documents/page/json-file-definition "JSON File Definition")
- [Understanding 2D Coordinate Systems in MIDILLI Tools](https://docs.midilli.tech/books/reference-documents/page/understanding-2d-coordinate-systems-in-midilli-tools "Understanding 2D Coordinate Systems in MIDILLI Tools")