name: bambu-slice
description: Slice a 3D model (STL/STEP/3MF) into a print-ready .gcode.3mf for the Bambu Lab A1 mini, and optionally upload + start the print. ALWAYS use this for any A1-mini slicing — driving OrcaSlicer's CLI directly silently produces WRONG output (it ignores Bambu's profile inheritance and reverts layer height/speeds/temps to defaults), and this skill flattens the profiles and verifies the result. Triggers on natural asks like "slice this for my A1", "get this STL ready to print", "make cube.stl printable on the a1", "print the benchy at 0.12mm on my a1 mini", or "I exported this from Fusion, need it on the bambu a1 mini in matte PLA" — including a freshly downloaded/exported STL or STEP, and choosing a layer height (0.08–0.28mm), nozzle, or filament; no slicer need be named. Do NOT use it when nothing needs slicing: controlling a live print (pause/resume/stop), calibration/bed-leveling, jogging axes, dashboard previews/thumbnails, or sending an already-sliced .gcode.3mf to the printer.
metadata:
type: reference
Slicing for the Bambu A1 mini (OrcaSlicer CLI) → print
Verified on a real A1 mini (OrcaSlicer 2.3.2 at /usr/bin/orca-slicer; system
profiles under /opt/orca-slicer/resources/profiles/BBL/{machine,process,filament}/).
The one trap you must know
OrcaSlicer's CLI does not resolve a profile's inherits chain. Bambu's
system profiles are diffs — 0.12mm Fine @BBL A1M.json doesn't contain
layer_height at all; it's in a grandparent. So --load-settings "<leaf>.json"
loads only the leaf's handful of keys and everything else silently falls back
to Orca's built-in defaults (layer_height → 0.2mm, plus default speeds/temps).
The result looks fine and even "works" for 0.2mm by coincidence, but any other
layer height (or any tuned setting) is quietly wrong. Never trust the profile
name — flatten the chain and verify the output.
Use the bundled helper (does the flatten + verify for you)
scripts/slice.py <model.stl> <out.gcode.3mf> [--layer 0.20] \
[--filament "Bambu PLA Basic @BBL A1M"] [--process "<process profile name>"]
It flattens the machine/process/filament inherits chains, slices, and fails
loudly if the produced layer height doesn't match the request. Examples:
scripts/slice.py /tmp/cube.stl /tmp/cube.gcode.3mf --layer 0.12
scripts/slice.py /tmp/cube.stl /tmp/cube.gcode.3mf
--layer: 0.08 / 0.12 / 0.16 / 0.20 / 0.24 / 0.28 (or any value → nearest
profile with the height forced). Default 0.20.
--filament: any … @BBL A1M name, e.g. Bambu PETG Basic @BBL A1M,
Generic PLA @BBL A1M, Bambu PLA Matte @BBL A1M.
--process: pass an exact process profile to honor its tuning (e.g.
0.20mm Strength @BBL A1M) instead of --layer.
--machine: defaults to Bambu Lab A1 mini 0.4 nozzle (use … 0.6 nozzle
etc. for other nozzles; then pick matching … 0.6 nozzle profiles).
Manual command (fallback — same trap applies)
If you slice by hand, you MUST resolve inheritance (the helper does this) and then
verify. The lazy --load-settings "<leaf>.json" form is only safe for the 0.2mm
default. Always confirm the real result:
unzip -p out.gcode.3mf Metadata/plate_1.gcode | grep -m1 '; layer_height'
unzip -l out.gcode.3mf | grep Metadata/plate_1.gcode
Headless caveat (thumbnails)
With no display the slice succeeds but logs init opengl failed! skip thumbnail generating — the gcode is fine, but the 3mf has no Metadata/plate_*.png (so
a dashboard preview is blank). For a thumbnail, run under xvfb-run -a ….
Upload + print
Project CLI (loads BAMBU_* from ./.env):
bambu file upload out.gcode.3mf --dest /
bambu job start --file /out.gcode.3mf --plate 1 --dry-run
bambu job start --file /out.gcode.3mf --plate 1 --confirm
bambu watch --exit-status
Or via bambu serve (HTTP, e.g. the dashboard):
B=http://HOST:8088
curl -X POST "$B/api/files/upload?dir=/&name=out.gcode.3mf" --data-binary @out.gcode.3mf
curl -X POST "$B/api/job/start" -H 'content-type: application/json' -d '{"file":"/out.gcode.3mf","plate":1,"dry_run":true}'
curl -X POST "$B/api/job/start" -H 'content-type: application/json' -d '{"file":"/out.gcode.3mf","plate":1,"confirm":true}'
Gotchas (observed on the real A1 mini)
- Clear the bed and ensure the printer is idle (
gcode_state ∈ IDLE/FINISH)
— job start refuses (409) when busy. Always --dry-run before a real print.
--export-3mf must be a bare filename when combined with --outputdir
(Orca concatenates them, otherwise the path doubles and export fails).
- The real settings preset is
Bambu Lab A1 mini 0.4 nozzle.json; the bare
Bambu Lab A1 mini.json is just a model descriptor, not a usable preset.
- AMS + single colour (verified on the real A1 mini): starting a single-filament
slice with
use_ams=false on an AMS-equipped A1 fails before the first layer
with print_error 0x03008015 — with no external spool, the printer has no source.
Verified fix: start with use_ams + an ams_map mapping the filament to a
loaded AMS slot, e.g. bambu job start … --ams-map "0" (or via the serve API,
{"use_ams":true,"ams_map":[0]}). A 12-layer test coin then ran start→FINISH with
print_error=0. (-1 in the map = external spool, if you load one and prefer that.)
Always --dry-run first and watch the first layer; the printer screen also shows
the plain-language cause.
Timelapse → use the bambu-timelapse skill
For a smooth per-layer timelapse (external camera, head parked out of the way each
layer), use the bambu-timelapse skill — it has the verified recipe and a slice
helper. Short version: use the A1's native time_lapse_gcode (a firmware-safe
absolute-Z lift + park) and arm it by starting the print with timelapse: true;
do not hand-roll a custom layer_change_gcode park.
An earlier version of this section recommended a custom park with a relative
G91/G1 Z0.3/G90 hop. That was disproven on the real A1: the firmware
mishandles relative Z in layer-change gcode and flattens every layer to the hop
height (a flat plate), and a no-hop park scrapes the print and detaches it
mid-print. The native path in bambu-timelapse avoids both.