platecli — local CLI for Bambu Lab printers (not affiliated with Bambu Lab)
Project description
platecli — local CLI for Bambu Lab printers
Fully local 3D printing pipeline for Bambu Lab printers. Runs on Linux, macOS, and Windows. The installed command is plate. Download models from Printables, slice with OrcaSlicer, and print — all controlled via CLI by any AI agent or by hand. No cloud account needed.
Supports: P1P, P1S, X1C, X1E, A1, A1 Mini (any Bambu printer with LAN mode)
Disclaimer: platecli is an unofficial, community-developed tool. It is not affiliated with, endorsed by, or supported by Bambu Lab. "Bambu Lab" and product names are trademarks of their respective owners, used here only to describe compatibility. The printer protocols (MQTT/FTPS) are reverse-engineered; a firmware update may break functionality without warning — run
plate doctorafter printer updates.
Status: Beta (0.2.0). Pre-1.0 — APIs and config keys follow the stability policy in docs/api.md.
Installation
The examples below use the installed plate command.
pipx install platecli
# or
uv tool install platecli
# or
pip install platecli
Previously published on PyPI as
bambu-local-cli(that release is yanked). The project is nowplatecli, and the installed command isplate.
Or from source:
pip install .
# or: uv sync
Try it without a printer
Before touching a real printer (or configuring one), sanity-check the install with simulation mode:
plate --sim status
🖨️ Bambu Printer Status
State: IDLE
Bed: 25°C / 0°C
Nozzle: 25°C / 0°C
Fan: 0 | WiFi: -42dBm
AMS:
Unit 0 (humidity 5, 26.0°C)
▶ Slot 0: PLA #F2F2F2 | 90%
Slot 1: PETG #0A0AC8 | 60%
Slot 2: empty
Slot 3: TPU #000000 | 45%
Agents should add --json for machine-readable output: plate --sim status --json.
Use with AI agents
--json is a global flag accepted by every command that produces structured output. Responses follow published JSON Schema files under docs/schemas/ — agents can validate against them or use them to understand the exact shape of each response.
--sim (simulation mode) replaces the real printer with a local stub, so an agent can develop, test, or exercise the full command surface without any hardware present.
Destructive and physical actions — starting a print, stopping a job, deleting a file, or sending raw G-code — are gated behind an explicit --confirm flag. An agent that omits --confirm will receive an error rather than trigger an action on the printer, making accidental physical operations impossible by default.
# Inspect printer state without hardware
plate --sim status --json
# Start a full print workflow — requires --confirm to actually begin printing
plate job <url> --json --confirm
Features
- Jobs & URL support — Use
jobwhen an agent or user gives either a website URL or a local file path. It handles everything in one shot. - Safe extraction — ZIP archives containing model files are fully supported. Existing files are kept safe by creating a numbered sibling such as
model-1.stl. URL downloads and ZIP extraction have a 2048 MB safety limit, adjustable via--max-download-mb. - Modularity — Run steps individually using
download,slice,upload, orprint. - Safety first — One-shot and print flows will not start a physical print unless
--confirmis present. Stop, delete, and raw gcode also require--confirm. - TLS pinning — Pin the printer’s self-signed cert with
cert_fingerprint(setup/doctor can capture it). Prefer this overinsecure_tls. - SSRF-hardened downloads — Private/loopback targets are refused unless you pass
--allow-private-ipsfor that invocation. - Diagnostics — Network, FTPS, and MQTT health checking with
doctorandpreflight. - Agent JSON — Structured
--jsonoutput with published schemas underdocs/schemas/.
Setup
Before running setup, gather your printer's LAN IP address, serial number, and
LAN-only access code (all shown on the printer's touchscreen under network/LAN
settings), and make sure LAN mode is enabled on the printer.
Use the interactive setup command to create your config securely:
plate setup
Inspect or check the resulting config at any time:
plate config show # print config path + contents (access code redacted)
plate config validate # check config values without contacting the printer
plate doctor # connectivity + live cert fingerprint
OrcaSlicer
Slicing shells out to OrcaSlicer, so plate needs to know where its binary
and bundled profiles/BBL directory live. Setup auto-detects the usual install
locations per platform — the macOS app bundle, the Windows Program Files
install, and on Linux a $PATH binary (orca-slicer), a Flatpak export, or an
AppImage under ~/Applications or ~/tools. If detection misses your install,
set orca_slicer and profiles_dir in config.json; when a configured path is
wrong, config validate (and slicing) will point you at a working OrcaSlicer it
found instead of failing with a generic error.
Usage
# Read-only: check connectivity and printer state (safe, no printer state changes)
plate status
plate doctor
For programmatic checks, plate --json --version emits JSON version details.
# Full workflow (download, slice, upload, and START A PHYSICAL PRINT)
# --confirm is required for any command that begins printing.
plate job "https://www.printables.com/model/12345-thing" --confirm --json
Monitoring a print
plate status --monitor (alias --wait) follows a print until it reaches a
terminal state (FINISH, FAILED, STOP, or IDLE). For a human it renders a
live progress bar; for an agent, add --json to stream newline-delimited
JSON (NDJSON) — one compact object per change as the print advances:
plate status --monitor --json
{"event":"update","command":"status","gcode_state":"RUNNING","mc_percent":42,"layer_num":50,"total_layer_num":200,"mc_remaining_time":33,"nozzle_temper":220,"nozzle_target_temper":220,"bed_temper":60,"bed_target_temper":60,"gcode_file":"model.gcode"}
{"event":"terminal","command":"status","gcode_state":"FINISH","mc_percent":100,"layer_num":200,"total_layer_num":200,"mc_remaining_time":0,"nozzle_temper":38,"nozzle_target_temper":0,"bed_temper":31,"bed_target_temper":0,"gcode_file":"model.gcode"}
Each line is a self-contained JSON object, so an agent can consume the stream
incrementally and stop once it sees "event":"terminal". Pair with --sim to
exercise the exact event shape without a printer. Schema: docs/schemas/status_event.json.
Global flags
| Flag | Description |
|---|---|
--json |
Emit JSON for commands that support it; may appear before or after the subcommand |
--sim |
Simulation mode (no real printer) |
--max-download-mb |
Cap URL download and ZIP extraction size (default 2048 MB); accepted by job, send, and download |
--allow-private-ips |
Allow downloads that resolve to private/loopback addresses (default: deny). CLI-only, not sticky config |
--network-timeout / --slicer-timeout / --command-timeout / --upload-timeout |
Bound long operations (see docs/api.md) |
Slicing & AMS
slice accepts common mesh formats in the precedence order STL > STEP > OBJ > 3MF > G-code. When mapping filaments to AMS slots, mapping arguments take zero-or-positive slot indexes.
To decide that mapping, read what is actually loaded first: plate status
shows each AMS unit's trays (filament type, colour, and remaining %), and
status --json includes a normalized ams block agents can consume directly:
"ams": {
"active_tray": 1,
"units": [
{"id": 0, "humidity": 4, "temp": 28.5, "trays": [
{"slot": 0, "type": "PLA", "color": "F2F2F2", "remain": 80, "empty": false, "active": false},
{"slot": 1, "type": "PETG", "color": "0A0AC8", "remain": 55, "empty": false, "active": true},
{"slot": 2, "type": null, "color": null, "remain": null, "empty": true, "active": false}
]}
]
}
ams is null on printers without an AMS. active marks the currently loaded
tray (absolute index unit * 4 + slot); feed the slot indexes to
--ams-mapping when printing with --use-ams.
Config reference
Config file location is platform-standard under the user config directory
(e.g. ~/.config/bambu/config.json on Linux). Create/edit via plate setup
or manually.
| Key | Required | Default | Description |
|---|---|---|---|
printer_ip |
✅ | — | Printer's LAN IP address |
serial |
✅ | — | Printer serial number |
access_code_file |
✅* | — | Path to file containing access code (recommended) |
access_code |
✅* | — | Inline access code (deprecated; migrate with plate setup --migrate-access-code) |
cert_fingerprint |
recommended | — | SHA-256 of the printer TLS cert (no separators or colon form both accepted) |
insecure_tls |
no | false |
Disable TLS verification (last resort; CLI warns when true) |
username |
no | bblp |
MQTT username |
mqtt_port |
no | 8883 |
MQTTS port |
model / printer_model |
no | P1P |
Printer model token for slicing |
nozzle / nozzle_size |
no | 0.4 |
Nozzle diameter string |
orca_slicer |
for slice | auto-detect | Path to OrcaSlicer binary |
profiles_dir |
for slice | auto-detect | Path to OrcaSlicer profiles/BBL directory |
camera_image |
no | bambu_p1_streamer |
Docker image for X1-style streamer fallback |
camera_container_name |
no | bambu_camera |
Docker container name |
camera_port |
no | 127.0.0.1:1985:1984 |
Docker publish mapping; loopback-only by default. Set to 0.0.0.0:1985:1984 to expose on the LAN (see SECURITY.md) |
camera_stream_url |
no | derived | Must be localhost if set; used for Docker frame fetch |
| Timeouts | no | package defaults | Optional network_timeout, slicer_timeout, command_timeout, upload_timeout (seconds) |
* Either access_code_file or access_code is required. Inline access_code is deprecated and will be removed in a future release.
allow_private_ips is not a config key — use the CLI flag --allow-private-ips per invocation.
Project layout
bambu_cli/— Runtime package used by the installed command (plate).scripts/bambu.py— Compatibility wrapper for direct script usage without installing.tests/— Unit, contract, security-marker, and smoke tests.docs/— API, schemas, quality roadmap, test backlog, mutation baseline, live smoke.
Documentation
Ships with the PyPI sdist (and on GitHub)
| Doc | Audience |
|---|---|
| AGENTS.md | Agents and automation (architecture, safety) |
| docs/api.md | JSON contracts + stability policy |
| docs/schemas/ | Machine-checkable JSON Schema files |
| SECURITY.md | Threat model, reporting, known limitations |
| CHANGELOG.md | Release notes |
Wheels contain runtime code only (no docs).
GitHub / contributor only (not in PyPI packages)
| Doc | Audience |
|---|---|
| CONTRIBUTING.md | Dev setup, tests, releases |
| docs/quality-roadmap.md | Quality scoreboard and phased plan |
| docs/test-backlog.md | Remaining test / coverage gaps |
| docs/live-printer-smoke.md | Opt-in real-printer harness |
| docs/mutation-baseline.md | Mutation testing scope and floor |
License
MIT — Use freely, modify as needed.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file platecli-0.2.0.tar.gz.
File metadata
- Download URL: platecli-0.2.0.tar.gz
- Upload date:
- Size: 237.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d70dfaf617ecc91954aaa6812b0d7ecb73d7f3709af0acdd2640a7d17fc0b305
|
|
| MD5 |
f6d774e5812af3836e150fea8fdab768
|
|
| BLAKE2b-256 |
2ab3f812681ef7359db075ea07fe0d525c4c53a426f517b5e92c0440fc32bd34
|
Provenance
The following attestation bundles were made for platecli-0.2.0.tar.gz:
Publisher:
release.yml on DLANSAMA/platecli
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
platecli-0.2.0.tar.gz -
Subject digest:
d70dfaf617ecc91954aaa6812b0d7ecb73d7f3709af0acdd2640a7d17fc0b305 - Sigstore transparency entry: 2228861963
- Sigstore integration time:
-
Permalink:
DLANSAMA/platecli@3f96d968ee5fd959bc364a80f740bd20791fdf49 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/DLANSAMA
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@3f96d968ee5fd959bc364a80f740bd20791fdf49 -
Trigger Event:
push
-
Statement type:
File details
Details for the file platecli-0.2.0-py3-none-any.whl.
File metadata
- Download URL: platecli-0.2.0-py3-none-any.whl
- Upload date:
- Size: 126.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9ebd8b756e9958e9cd16ea9bac71309920f206fc0fdb0ff5c99db5fee4ce5afb
|
|
| MD5 |
6489bc485394f87b0bf3a1afcc05e1f1
|
|
| BLAKE2b-256 |
0dca08b806e59be77863c309b2ab4838d2bfb8cd279f6b70eb41939255e66a69
|
Provenance
The following attestation bundles were made for platecli-0.2.0-py3-none-any.whl:
Publisher:
release.yml on DLANSAMA/platecli
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
platecli-0.2.0-py3-none-any.whl -
Subject digest:
9ebd8b756e9958e9cd16ea9bac71309920f206fc0fdb0ff5c99db5fee4ce5afb - Sigstore transparency entry: 2228862867
- Sigstore integration time:
-
Permalink:
DLANSAMA/platecli@3f96d968ee5fd959bc364a80f740bd20791fdf49 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/DLANSAMA
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@3f96d968ee5fd959bc364a80f740bd20791fdf49 -
Trigger Event:
push
-
Statement type: