bambu-rs
English · 日本語
A command-line tool and library for monitoring and controlling Bambu Lab 3D printers over the LAN — for a person at the terminal or an AI agent.
It's a clean-room implementation: built from the protocol documentation
(OpenBambuAPI) and direct observation of
real hardware, with no dependency on — or reference to — existing Bambu libraries
(the observed protocol facts are written up in docs/protocol.md).
Four mechanisms make it safe to automate: machine-readable JSON (--json), a semantic
exit-code scheme, --confirm/--dry-run gates on every physical action, and
verify-by-reread — success is confirmed by re-reading the printer's own report, not by
the command going through.
The bambu CLI is designed around an interface that's easy for an AI agent to drive.
⚠️ Only tested on my own A1 mini in LAN mode. Other models / firmware are unverified — treat them as best-effort. It talks to the printer directly, with no cloud in the path; controlling a print needs LAN-only + Developer Mode on the printer, though just reading state doesn't.
Install
# prebuilt binary — dashboard included
# build from crates.io
# ...or with the dashboard (needs node + pnpm to build the web UI)
Prebuilt binaries for Linux, macOS, and Windows are attached to every release.
Usage
# one-time: register a printer (the 8-digit LAN access code is on the printer's screen)
# read state — one-shot JSON, or --watch to follow the active print to completion
# files on the printer (FTPS): ls / upload / download / rm
# calibrate — with no routine flag it runs them all (bed level, vibration, motor noise)
# start a print: preview the resolved plan, then run it with guards and watch it
# or upload a local file and start it in one step
Reading state takes no flags and no checks — just a connect and a snapshot. Physical actions
(job start/pause/resume/stop, temp, light, gcode, ams, calibrate), by contrast,
require --confirm and check the printer's own state first (idle, no errors, the expected
file/plate). The exit code distinguishes success / unverified / rejected / busy so scripts and agents
can branch on it, and --json makes the output machine-readable.
Slicing
bambu-rs doesn't slice — it delegates to Bambu Studio / OrcaSlicer's CLI to
produce a sliced .gcode.3mf, then uploads and prints it:
# 1. Slice a model to .gcode.3mf (Bambu Studio / OrcaSlicer CLI)
# 2. Upload, preview the plan, then print it (asserting it's exactly what you inspected)
Full details (flags, AMS mapping, external spool, --dry-run) in
docs/slicing.md.
Dashboard
bambu serve runs a small local server. With the dashboard feature enabled, it serves the
web dashboard built into the CLI (without it, you still get the REST API). From a phone or
browser you get live printer status, temperatures, AMS, the live camera, one-click
clean-timelapse capture, and the usual controls — all over the same single LAN connection
(reads are open; control is gated behind an optional password).
Timelapse
The printer's own built-in timelapse works as you'd expect: toggle recording with
bambu timelapse enable/disable, opt in per print with job start --timelapse, and fetch
the finished video with bambu timelapse get. Beyond that, bambu-rs can record your own
from an external camera, driven by the print's own layer events — one frame per layer. It
also covers printers whose built-in camera is missing or broken.
There are two ways to feed it. Point bambu timelapse capture at any tool to grab a frame
each layer (the command after -- runs as argv, never via a shell, with
{frame}/{layer}/{outdir} substituted in):
# a USB camera served over HTTP by µStreamer (its /snapshot endpoint):
# an IP camera (e.g. an ATOM Cam running atomcam_tools) over plain HTTP:
Or, for the smooth result above, bambu timelapse park reads a camera's MJPEG stream and
picks the parked frame for each layer on-device — the head clear of the object — so you
don't have to time the grab yourself. The bambu serve dashboard wraps the same into
one-click capture:
Either way, a failed grab is skipped and a suggested ffmpeg line is printed to stitch the
frames.
More commands
Physical actions take --confirm; ams change/set-filament also support --dry-run.
Deeper slicer integration comes later.
Library
The protocol and safety logic live in a reusable Rust crate — the bambu CLI and the
bambu serve dashboard are both just consumers of it.
[]
= { = "0.1", = false } # library only — no CLI/server deps
use LanMqttClient;
use ResolvedTarget;
use ;
use Model;
use CommandOutcome;
let client = new;
// Full calibration. `send_and_verify` confirms the routine actually started by
// re-reading the printer's own report — not just that the publish succeeded.
let outcome = client.send_and_verify?;
assert_eq!;
// Print a sliced 3MF already uploaded to the printer (plate 1).
let job = new;
client.send_and_verify?;
Per-firmware differences are captured as capabilities of a given (model, firmware): how
the camera streams (the A1 sends JPEG over a raw TCP socket; X-series printers use RTSP),
whether a temperature command is still honoured once a print is running (newer firmware
silently ignores it), whether state arrives as one full snapshot or as deltas, even a field
name whose spelling changed between releases. The set is resolved once on connect, and
command-building, report parsing, and the safety checks all read from it instead of
scattering if firmware >= … branches through the code. bambu info prints it for the
connected printer:
$ bambu info
printer: a1 (a1mini)
firmware: 01.07.02.00
registry: supported
push: delta_only
camera: jpeg_tcp_6000
control: requires_developer_mode — control needs LAN-only + Developer Mode enabled
modules:
ota hw OTA sw 01.07.02.00 Bambu Lab A1 mini
esp32 hw AP05 sw 01.16.39.58
mc hw MC02 sw 00.01.30.10
th hw TH03 sw 00.00.07.72
ams_f1/0 hw AMS_F102 sw 00.00.08.15 AMS Lite