Skip to content
voskaPublic

About

Slice, preflight, send and monitor Bambu Lab prints from the command line — LAN mode, agent-friendly

Topics

Resources

Security policy

Stars

6 stars

Watchers

0 watching

Forks

Repository files navigation

CI Release Go License: MIT

bambu

Migrating the Python Print Operator? See the command and configuration guide.

Slice, check, send and monitor Bambu Lab prints from the terminal over your LAN. It's built for humans and for AI agents.

  • Headless slicing: it drives the Bambu Studio CLI with the correct system presets for your printer and nozzle, plus recipes and --set overrides.
  • Safety first:
    • Preflight gates check that the printer is idle, the right filament is in the slot, the plate and nozzle match, Developer Mode is on, and there's enough filament.
    • print send refuses to run without --confirm.
    • AMS spool metadata edits require --confirm and verified read-back. AI protections and network settings stay read-only.
  • LAN only: MQTT and FTPS go directly to the printer. No cloud account, no Bambu Connect.
  • Agent-friendly: --json everywhere (NDJSON for streams), stable exit codes, schema introspection, and no prompts with --no-input.
  • Single static binary for macOS, Linux and Windows.
$ bambu status
workshop (192.168.1.50)  IDLE / idle   dev_mode=true  sdcard=true  liveview=true
  temps    nozzle 26/0  bed 24/0   nozzle 0.4 mm hardened_steel
  errors   none
  AMS A1   PLA    PLA Matte    #FF6A13  33% (~330 g)
  AMS A2   PETG   PETG Basic   #FFFFFF  80% (~800 g)
  protect  first_layer=true spaghetti=true halt=true (medium)

$ bambu slice bracket.stl --recipe functional-petg
sliced  bracket-functional-petg
  time      35m 38s  (2138 s)
  filament  13.22 g PETG (GFG00)   layers 113
  temps     bed 70 C (textured_plate)   nozzle 252 C, first layer 252 C
  3mf       ./bracket-functional-petg.gcode.3mf

$ bambu print send bracket-functional-petg.gcode.3mf --slot A2 --dry-run   # preflight + exact payload, sends nothing
$ bambu print send bracket-functional-petg.gcode.3mf --slot A2 --confirm   # after you've checked the plate is clear
$ bambu monitor --snapshot-at-layer 2

Requirements

  • A Bambu Lab printer in LAN Only mode with Developer Mode enabled. Since the January 2025 "Authorization Control" firmware, the printer rejects unsigned third-party control commands otherwise.
    • On the printer, go to Settings → LAN Only, enable LAN Only Mode, then Developer Mode. Note the access code shown there.
    • Developer Mode disconnects the printer from Bambu Cloud and the Handy app. That's Bambu's tradeoff, not ours.
    • Status (bambu status) is read-only and works without Developer Mode. FTPS upload and control need it.
  • Bambu Studio installed, for slice.
  • ffmpeg, for camera snapshots.
  • Tested models: X1 Carbon. The X1/X1E/P1/A1/H2/P2S series use the same LAN protocol and should work, but they are untested. Camera snapshots are X1/H2/P2S-series only for now; P1/A1 use a different camera protocol.

Install

brew install voska/tap/bambu            # macOS / Linux
go install github.com/voska/bambu/cmd/bambu@latest

Binaries for macOS, Linux and Windows are on Releases.

Setup

# 1. Add the printer (IP + serial from the printer's Settings, or use discovery)
bambu printer discover                       # listens for the printer's SSDP broadcast (UDP 2021)
bambu printer add workshop --host 192.168.1.50 --serial 00M00A000000000 --model X1C --nozzle 0.4 --plate textured_plate

# 2. Store the access code in the OS keychain (read from stdin; verified against the printer, read-only)
bambu auth set workshop                      # prompts; or: echo CODE | bambu auth set workshop

# 3. Check
bambu auth status --check
bambu slicer info
bambu status

Config: ~/.config/bambu/config.toml (%AppData%\bambu\config.toml on Windows, or $BAMBU_CONFIG). Printers are named, and --printer/BAMBU_PRINTER picks one. bambu only reads and writes config.toml, so it coexists with other tools that use ~/.config/bambu/config.json.

Access code: looked up in this order:

  1. The OS keychain (service bambu, account = the printer serial)
  2. BAMBU_ACCESS_CODE
  3. Bambu Studio's BambuStudio.conf, as a last-resort fallback

It is never printed, and never written to the config.

Workflow

bambu recipe list                                   # prototype-pla, solid-pla, functional-pla, functional-petg
bambu slice part.3mf --recipe solid-pla             # STL / 3MF / OBJ
bambu slice part.stl --recipe prototype-pla --set wall_loops=3 --filament "Bambu PLA Matte"
bambu slice one.stl two.stl three.stl --recipe solid-pla --part-spacing 3
bambu camera snapshot -o plate.jpg                  # look at the plate
bambu preflight part-solid-pla.gcode.3mf --slot 4   # PASS/WARN/FAIL gates
bambu print send part-solid-pla.gcode.3mf --slot 4 --confirm
bambu monitor --snapshot-at-layer 2 --exec 'notify-send "$BAMBU_EVENT $BAMBU_STATE"'

Multiple inputs remain separate objects. Studio arranges them on one plate with at least 3 mm between parts; --part-spacing can increase that gap. Orientation is preserved unless --auto-orient is given. Batches that need several plates fail before publishing.

print send records a timelapse by default. --no-timelapse disables it for one print; --timelapse explicitly enables it. To change the default in config.toml:

[print]
timelapse = false

X1C preflight checks first-layer object extrusion against the startup lines at X18–240 / Y0–12 and the X0–18 / Y0–28 corner, with a 1 mm margin. Collisions fail. Missing or unsupported toolpaths report NOT VERIFIED and fail with --strict or print send --dry-run. Travel and startup extrusion are excluded.

Two colours

A two-filament job changes colour at a layer height, and the AMS swaps by itself: no pause, nobody at the printer.

bambu slice sign.3mf --recipe prototype-pla \
  --filament "Generic PLA" --color FFFFFF --filament "Bambu PLA Matte" --color 000000 \
  --filament-change-z 4.0                           # white through Z 4.0, black from the next layer up
bambu print send sign-prototype-pla.gcode.3mf --slot A4 --slot A1 --dry-run   # one slot per filament, in order
  • --filament-change-z must be a layer top. slice reads the change back from the G-code and fails (exit 11) if Bambu Studio didn't place it.
  • The summary has grams per filament, including purge and prime-tower waste, and filament_changes.
  • To change colour by hand at a pause (e.g. a spool that isn't in the job), bambu filament load --slot A1 --confirm swaps the toolhead to another AMS slot remotely, then bambu print resume --confirm.

Recipes

Recipes name presets generically ("0.20mm Standard", "Bambu PLA Basic"), and bambu resolves the right system preset for your printer model and nozzle.

recipe for settings
prototype-pla fit/form checks PLA Basic, 0.20 Standard, 2 walls, 15% gyroid
solid-pla solid PLA parts Generic PLA, 6 walls (inner 0.45), 100% zig-zag
functional-pla strong PLA parts 6 walls @ 0.45, 100% zig-zag, 5 top/bottom, elephant-foot 0.15
functional-petg strong/warm/outdoor parts as functional-pla in PETG Basic; 252 °C, 70 °C bed, fan ≤ 30%
  • No recipe adds a brim. Brims are opt-in: --set brim_type=outer_only --set brim_width=5.
  • Custom recipes: drop JSON files in ~/.config/bambu/recipes/. The same name overrides a built-in. See bambu recipe show solid-pla.
  • --set key=value takes any Bambu Studio setting key. Unknown keys are rejected before slicing. At 100% infill, patterns the slicer rejects (grid, gyroid, …) switch to zig-zag automatically.

Configure an AMS spool

After loading a non-RFID spool, record what is physically in the slot:

bambu ams set --slot A1 --type PLA --filament-id GFL99 --color C8A26B \
  --nozzle-temp-min 200 --nozzle-temp-max 230 --dry-run --json
# Use --confirm instead of --dry-run to apply the same values.

GFL99 is Generic PLA; PLA+ uses material type PLA. Supply the matching profile ID, preview color, and temperature range from the spool manufacturer. Common Generic profile IDs are type-checked; matching other IDs to the material is the caller's responsibility. A wood-colored PLA+ spool uses a PLA profile; a wood-filled material needs its own suitable profile.

All five material fields are required so a changed spool does not inherit old values. The printer must be idle, in Developer Mode, and detect filament in the slot. Paused jobs, busy AMS operations, empty or unknown slots, and RFID spools are refused. Dry-run runs the same gates and shows the protocol payload without changing anything. Exit 0 on a write means a fresh tray report matched every field, including color alpha; an acknowledgement alone is insufficient. Repeating the same values sends nothing.

This records metadata without loading filament or heating the printer. Temperature bounds are used by later filament loads and preflight checks. Bed temperature, flow ratio, and volumetric speed belong to the slicing profile; this command also leaves the tray's flow calibration unchanged and reports any calibration telemetry before and after. Only use it after a human identifies the physical spool, never to bypass a preflight mismatch.

Download timelapses

bambu timelapse list --json
bambu timelapse pull --latest -o ./latest-print.mp4
bambu timelapse pull video_2026-01-02_03-04-05.mp4 -o ./videos/

These commands read .mp4 and .avi files directly under the printer's /timelapse/ directory using the configured LAN access code. Lists are ordered by modification time, then filename, newest first. JSON includes printer and timelapses entries with name, bytes, and UTC mtime; an empty list exits 3. Use --quiet for filenames or the absolute downloaded path, or --plain for TSV. --latest skips zero-byte recording placeholders; requesting an empty video by name exits 1.

-o accepts a file path or an existing directory; without it, the video is saved in the current directory under its original name. Downloads never overwrite local files or change printer files. A failed or changing transfer leaves no completed file and exits 8; retry after recording finishes. Publishing the verified download requires a local filesystem with hard-link support. Recording must have been enabled when sending the job (print send --timelapse). Downloaded files are owner-only (0600).

Safety model

  1. preflight checks before anything is sent:

    • the printer is idle, with no blocking errors (informational HMS codes like "Inspecting first layer" are ignored)
    • Developer Mode is on and an SD card is present
    • the 3MF is intact and sliced for this printer model, with one --slot per filament
    • the nozzle diameter and plate match
    • each slot is loaded with its filament's type (a different product of that type is a WARN)
    • each slot has enough filament (unknown remaining is a WARN), and the temperatures are sane
    • the printer's AI protections are on (WARN only) and FTPS login works
  2. print send re-runs preflight and refuses on any FAIL. It requires --confirm, uploads over FTPS, reads the file back to verify its MD5, then starts the job with bed leveling, flow calibration, vibration compensation and first-layer inspection on.

  3. print pause|resume|stop require --confirm. resume exits 0 only once the printer reports RUNNING. It refuses mid-filament-change, and with an empty toolhead on the X1 series.

  4. filament load requires --confirm and works only while paused or idle. When paused, the toolhead must hold an AMS filament and the slot must hold the same material. It exits 0 only once the printer reports that slot in the toolhead.

  5. ams set requires --confirm to record non-RFID spool metadata while idle, with physical filament detection and verified read-back. --dry-run sends nothing.

AI protections, network settings, and direct temperature controls remain read-only.

If the AMS remaining estimate is wrong, check the spool and pass --filament-remaining A2=50g to preflight or print send. Repeat the flag for each checked slot. The estimate applies only to that invocation and must cover the job's filament use plus 15% and 5 g. A sufficient estimate reports filament_amount as WARN with both the stated amount and AMS reading, including with --strict. An insufficient estimate stays FAIL. The slot must still be loaded with the right material, and all other gates and --confirm still apply.

Exit codes

bambu exit-codes

code meaning
0 success
1 error
2 usage
3 empty
4 auth required / code refused
5 not found
6 forbidden (Developer Mode off)
8 retryable (unreachable/timeout)
9 gate failed (preflight FAIL, missing --confirm, busy)
10 config error / slicer not found
11 slice failed
12 print failed
13 print paused, needs a human
14 monitor timeout

For AI agents

  • bambu schema --json returns the full command tree with flags. bambu schema print send returns one command.
  • Every command takes --json. Errors come back as {"error":{"code","name","message","hint"}}, and the hint says what to do next.
  • status --watch --json and monitor --json stream NDJSON events.
  • There's an agent skill in skills/bambu/SKILL.md. The recommended flow: status → slice → dry-run → show the human the summary, preview and snapshot → --confirm only after explicit approval.

Slicer support

  • Bambu Studio is discovered in this order:

    1. BAMBU_STUDIO_PATH / [slicer] path
    2. /Applications/BambuStudio.app (macOS)
    3. bambu-studio in the usual Linux paths, Flatpak, or an extracted AppImage
    4. Program Files\Bambu Studio (Windows)

    Only macOS is tested. A packed AppImage can't be read, so extract it (--appimage-extract) or set [slicer] resources.

  • Presets are flattened by bambu. The Bambu Studio CLI does not resolve inherits/include in preset files. Unflattened presets slice "successfully" with a generic 200×200 bed and no printer start G-code.

  • STEP is not supported by the Bambu Studio CLI. Export STL or 3MF instead.

  • OrcaSlicer isn't supported yet. Its 2.4.x CLI has the same inherits problem (fixed upstream after 2.4.2).

Credits

The LAN protocol details come from these open projects' public documentation and code. No code was copied.

  • OpenBambuAPI (GFDL docs): MQTT, FTPS and video.
  • ha-bambulab (MIT): HMS decoding, stage names, print.fun Developer Mode bit, project_file usage.
  • bambulabs_api (MIT): implicit FTPS with TLS session reuse.
  • Bambu Studio (AGPL-3.0): preset resolution order and AMS mapping format were read from its source; bambu invokes the installed app and ships none of its files.

Not affiliated with Bambu Lab. "Bambu Lab" is a trademark of its owner.

License

MIT

About

Slice, preflight, send and monitor Bambu Lab prints from the command line — LAN mode, agent-friendly

Topics

Resources

Security policy

Stars

6 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages