klipper-manager
Skill: klipper-manager
Klipper Manager — Full AI-Driven Printer Configuration & Diagnostics
Manages any Klipper printer via Moonraker API: reads and edits printer.cfg, runs diagnostics, executes calibration sequences, monitors live status, and fixes issues with full config-awareness.
Activation
When the user asks to:
- Connect to / manage a Klipper printer
- Read, change, or fix any printer.cfg setting
- Diagnose a Klipper error or warning
- Run calibration (bed mesh, probe, PID, resonances, pressure advance, axis twist, screws, etc.)
- Monitor temperatures, positions, or print status
- Send GCode commands
- Restart firmware or Klipper
Always start by reading state/printer_context.json — if it exists, greet the user with
a summary of the known printer. If it is missing or the user provides a new IP, run Phase 1.
Phase 1: Printer Discovery
Step 1 — Connect to Moonraker
Ask for the printer IP if not already known. Then verify connectivity:
curl -s "http://<IP>:7125/printer/info"
Expected response contains: state, hostname, software_version, config_file.
If state is not "ready", report it and ask the user to resolve before continuing.
Step 2 — Fetch printer.cfg
curl -s "http://<IP>:7125/server/files/config/printer.cfg"
Also fetch any included files referenced with [include ...]:
curl -s "http://<IP>:7125/server/files/config/<included_file>"
Common includes to auto-fetch: mainsail.cfg, macros/*.cfg, KAMP/*.cfg.
Step 3 — Parse and Inventory Config
Parse ALL sections from the fetched config. Extract and store in state/printer_context.json:
{
"version": 1,
"updated": "ISO-8601",
"moonraker_url": "http://<IP>:7125",
"klipper_version": "v0.13.x",
"hostname": "mainsailos",
"config_file": "/home/pi/printer_data/config/printer.cfg",
"kinematics": "cartesian | corexy | corexz | delta | ...",
"build_volume": {"x": 235, "y": 235, "z": 250},
"steppers": {
"stepper_x": {"position_max": 246, "position_min": 0, "rotation_distance": 40, "microsteps": 16},
"stepper_y": {"position_max": 235, "position_min": 0},
"stepper_z": {"position_max": 250, "position_min": -2}
},
"probe": {
"type": "bltouch | probe | smart_effector | probe_eddy_current | none",
"x_offset": -62,
"y_offset": -12,
"z_offset": 3.439
},
"bed_mesh": {
"mesh_min": [60, 30],
"mesh_max": [170, 220],
"probe_count": [5, 5]
},
"axis_twist_compensation": {
"calibrate_start_x": 20,
"calibrate_end_x": 183,
"calibrate_y": 117.5
},
"safe_z_home": {
"home_xy_position": [108.5, 117.5]
},
"extruder": {
"nozzle_diameter": 0.4,
"rotation_distance": 7.687,
"pressure_advance": null
},
"tmc_drivers": {
"stepper_x": {"driver": "tmc2209", "run_current": 0.750, "stealthchop_threshold": 999999},
"stepper_y": {"driver": "tmc2209", "run_current": 0.750, "stealthchop_threshold": 999999},
"stepper_z": {"driver": "tmc2209", "run_current": 0.580, "stealthchop_threshold": 0},
"extruder": {"driver": "tmc2209", "run_current": 0.580, "stealthchop_threshold": 0}
},
"input_shaper": {
"x": {"type": "3hump_ei", "freq": 66.2},
"y": {"type": "ei", "freq": 45.0}
},
"printer_limits": {
"max_velocity": 300,
"max_accel": 7000,
"max_z_velocity": 15,
"max_z_accel": 100
},
"installed_sections": [],
"save_config_block": {},
"known_issues": [],
"last_diagnostic": null
}
Step 4 — Run Auto-Diagnostic
After parsing, always run the full diagnostic (see Phase 3) and report any issues found.
Step 5 — Present Summary
Show the user a table:
Printer : mainsailos (Klipper v0.13.x)
Kinematics : Cartesian | Build: 246 × 235 × 250 mm
Probe : BLTouch | x_offset: -62 y_offset: -12 z_offset: 3.439
Sections : [printer] [extruder] [heater_bed] [bltouch] [bed_mesh] [axis_twist_compensation]
[input_shaper] [firmware_retraction] [safe_z_home] [screws_tilt_adjust] ...
Issues : (list any found by diagnostic, or "None detected")
Phase 2: Configuration Management
Reading a Setting
To read any setting, look up the parsed printer_context.json or re-fetch the file:
curl -s "http://<IP>:7125/server/files/config/printer.cfg"
Editing a Setting
Workflow for every config change:
- Fetch the CURRENT file (never edit a stale copy)
- Make the targeted change
- Validate the change (see Phase 3 validation rules)
- Save to a temp file
C:/Users/<user>/Documents/printer_fix.cfg - Upload via Moonraker:
curl -s -X POST "http://<IP>:7125/server/files/upload" \ -F "root=config" \ -F "file=@C:/Users/<user>/Documents/printer_fix.cfg;filename=printer.cfg" - Firmware restart to apply:
curl -s -X POST "http://<IP>:7125/printer/firmware_restart" - Wait 5 seconds, verify
state: ready:curl -s "http://<IP>:7125/printer/info" - Update
state/printer_context.json - Clean up temp file
CRITICAL: Never edit the SAVE_CONFIG block by hand. Only Klipper's SAVE_CONFIG command
should modify that block. When uploading a modified config, preserve the entire #*# <--- SAVE_CONFIG ---> block exactly as-is unless explicitly removing stale calibration data.
Multiple Config Files
If the printer uses [include] sections, list all config files:
curl -s "http://<IP>:7125/server/files/list?root=config"
Fetch and edit the correct file — do not modify printer.cfg when the target section lives in an included file.
Phase 3: Diagnostics & Validation
Auto-Diagnostic Checklist
Run this every time a config is loaded or after any change. Check ALL rules:
1. Probe Offset Bounds
For every calibration section that uses probe coordinates, the nozzle must stay within
[position_min, position_max] accounting for probe offsets.
| Section | Coord params | Nozzle position formula |
|---|---|---|
[axis_twist_compensation] |
calibrate_start_x, calibrate_end_x, calibrate_y |
nozzle_x = coord_x - probe.x_offset; nozzle_y = coord_y - probe.y_offset |
[bed_mesh] |
mesh_min, mesh_max |
nozzle_x = mesh_x - probe.x_offset; nozzle_y = mesh_y - probe.y_offset |
[screws_tilt_adjust] |
screw1..N (x,y) |
nozzle_x = screw_x - probe.x_offset; nozzle_y = screw_y - probe.y_offset |
[safe_z_home] |
home_xy_position |
These are NOZZLE coords directly (no offset subtraction needed) |
[delta_calibrate] |
radius |
probe must land within radius from center accounting for offset |
Validate for each axis:
nozzle_x >= stepper_x.position_min AND nozzle_x <= stepper_x.position_max
nozzle_y >= stepper_y.position_min AND nozzle_y <= stepper_y.position_max
Fix formula:
max_coord_x = stepper_x.position_max + probe.x_offset (when x_offset is negative)
min_coord_x = stepper_x.position_min - probe.x_offset (when x_offset is positive)
2. Bed Mesh Bounds
mesh_min and mesh_max must be within the reachable probe area:
mesh_min.x >= stepper_x.position_min - probe.x_offset
mesh_max.x <= stepper_x.position_max + probe.x_offset (when x_offset < 0)
mesh_min.y >= stepper_y.position_min - probe.y_offset
mesh_max.y <= stepper_y.position_max + probe.y_offset (when y_offset < 0)
3. Safe Z Home Position
home_xy_position must be reachable for the NOZZLE:
home_xy.x >= stepper_x.position_min AND home_xy.x <= stepper_x.position_max
home_xy.y >= stepper_y.position_min AND home_xy.y <= stepper_y.position_max
Also validate that at the home position, the PROBE is over the bed (not hanging off the edge).
4. SAVE_CONFIG / Calibration Consistency
After a config change, check if saved calibration data in #*# SAVE_CONFIG is still valid:
- If
axis_twist_compensationbounds changed → oldz_compensations/compensation_start_x/compensation_end_xmay be stale → warn user to re-runAXIS_TWIST_COMPENSATION_CALIBRATE - If
bltouch.z_offsetorprobe.z_offsetwas manually changed → warn thatPROBE_CALIBRATEshould be re-run - If
bed_meshbounds changed → existing mesh profiles may be out of bounds → warn to re-runBED_MESH_CALIBRATE
5. TMC Driver Warnings
stealthchop_threshold: 999999on extruder with pressure advance → warn (reduced torque, but often acceptable)hold_currentconfigured → warn (can cause vibration, Klipper docs recommend omitting)run_current> rated motor current × 0.85 → warn (thermal risk)interpolate: Truewith high-precision requirements → note positional deviation (~0.006mm at 16 microsteps)
6. Input Shaper
shaper_type: 3hump_eior2hump_ei→ complex resonance signature → recommend belt tension check- No
[input_shaper]section → recommend runningSHAPER_CALIBRATE - Shaper frequency < 20Hz → likely miscalibrated or very heavy toolhead
7. Pressure Advance
pressure_advancenot set (0 or absent) in[extruder]→ recommend calibrationpressure_advance > 1.0→ unusually high, check rotation_distance and extruder type
8. Rotation Distance Sanity
For extruder:
- Direct drive:
rotation_distanceshould be 4–10 (typical 7–8 for BMG-style) - Bowden:
rotation_distanceshould be 20–40
For motion axes:
- GT2 belt, 20-tooth pulley:
rotation_distance = 40 - GT2 belt, 16-tooth pulley:
rotation_distance = 32 - T8 leadscrew (2mm pitch, 4 starts):
rotation_distance = 8 - T8 leadscrew (2mm pitch, 1 start):
rotation_distance = 2
9. PID Tuning
control: watermark→ old method, recommend PID calibrationpid_Kp,pid_Ki,pid_Kdabsent → heater has no PID, may be unstable
10. Missing Recommended Sections
Flag as warnings (not errors):
- No
[exclude_object]→ object cancellation unavailable - No
[firmware_retraction]→ runtime retraction tuning unavailable - No
[gcode_arcs]→ arc support unavailable - No
[respond]→ macro feedback may be silent - No
[pause_resume]→ pause/cancel prints may not work
Phase 4: Live Status Monitoring
Query Printer Objects
Klipper exposes live state via Moonraker's objects API:
# Query everything
curl -s "http://<IP>:7125/printer/objects/query?toolhead&extruder&heater_bed&bed_mesh&probe&print_stats"
# Query specific fields
curl -s "http://<IP>:7125/printer/objects/query?toolhead=position,max_velocity,max_accel&extruder=temperature,target,pressure_advance"
Key objects and fields:
| Object | Key fields |
|---|---|
toolhead |
position, homed_axes, max_velocity, max_accel, stalls |
extruder |
temperature, target, pressure_advance, can_extrude |
heater_bed |
temperature, target, power |
probe or bltouch |
last_query, last_probe_position |
bed_mesh |
profile_name, mesh_min, mesh_max, probed_matrix |
print_stats |
state, filename, total_duration, filament_used |
idle_timeout |
state, printing_time |
motion_report |
live_position, live_velocity |
firmware_retraction |
retract_length, retract_speed |
input_shaper |
(queried from configfile) |
tmc2209 stepper_x |
run_current, hold_current, drv_status, temperature |
configfile |
save_config_pending, settings.<section>.<key> |
webhooks |
state, state_message |
system_stats |
sysload, cputime, memavail |
Send GCode
curl -s -X POST "http://<IP>:7125/printer/gcode/script" \
-H "Content-Type: application/json" \
-d '{"script": "QUERY_ENDSTOPS"}'
Query Endstops
curl -s "http://<IP>:7125/printer/query_endstops/status"
Phase 5: Calibration Sequences
Probe Z-Offset (PROBE_CALIBRATE)
- Verify printer is homed: send
G28 - Start calibration:
PROBE_CALIBRATE - Guide user through paper test at nozzle
- Accept:
TESTZ Z=-0.1(adjust in steps) - Finalize:
ACCEPT - Save:
SAVE_CONFIG(triggers firmware restart automatically)
Bed Mesh Calibration
- Home all axes:
G28 - Optional: heat bed to print temp first
- Run:
BED_MESH_CALIBRATE - Save profile:
BED_MESH_PROFILE SAVE=default - Save to config:
SAVE_CONFIG
Axis Twist Compensation
Before running, always validate calibrate_end_x:
max_safe_end_x = stepper_x.position_max + probe.x_offset
If calibrate_end_x > max_safe_end_x → fix it first (see Phase 2 edit workflow)
Then:
- Home:
G28 - Run:
AXIS_TWIST_COMPENSATION_CALIBRATE - Follow prompts for paper test at each probe point
- Save:
SAVE_CONFIG
PID Tuning
Hotend:
PID_CALIBRATE HEATER=extruder TARGET=200
SAVE_CONFIG
Bed:
PID_CALIBRATE HEATER=heater_bed TARGET=60
SAVE_CONFIG
Pressure Advance
Method 1 — Tuning tower (manual):
SET_VELOCITY_LIMIT SQUARE_CORNER_VELOCITY=1 ACCEL=500
TUNING_TOWER COMMAND=SET_PRESSURE_ADVANCE PARAMETER=ADVANCE START=0 FACTOR=.005
Print a tuning tower model. Measure optimal layer. Calculate:
PA = START + FACTOR × best_layer_height_mm
Method 2 — Set directly after finding value:
SET_PRESSURE_ADVANCE ADVANCE=0.04
Then add to [extruder] in config and SAVE_CONFIG.
Resonance / Input Shaper Calibration
- Verify
[adxl345]or other accelerometer configured - Home:
G28 - Test accelerometer:
ACCELEROMETER_QUERY - Measure noise baseline:
MEASURE_AXES_NOISE - Calibrate X:
SHAPER_CALIBRATE AXIS=X - Calibrate Y:
SHAPER_CALIBRATE AXIS=Y - Review results and apply recommended shaper
SAVE_CONFIG
Screws Tilt Adjust
- Home:
G28 - Run:
SCREWS_TILT_CALCULATE - Read output — each screw shows turn direction (CW/CCW) and amount (HH:MM)
- Re-run until all screws show < 0:05 deviation
TMC Driver Diagnostics
Dump driver state:
DUMP_TMC STEPPER=stepper_x
DUMP_TMC STEPPER=stepper_y
DUMP_TMC STEPPER=stepper_z
DUMP_TMC STEPPER=extruder
Adjust current at runtime (test only — add to config to persist):
SET_TMC_CURRENT STEPPER=stepper_x CURRENT=0.8 HOLDCURRENT=0.5
Phase 6: Troubleshooting
Use references/troubleshooting.md for the full error → cause → fix database.
Workflow for any error message the user pastes:
- Extract the error pattern (error type + coordinates/values if present)
- Match against known patterns in the troubleshooting reference
- Pull the relevant config sections from
printer_context.json - Compute the specific fix values using the validation formulas
- Present the diagnosis with the exact lines to change
- Offer to apply the fix automatically (Phase 2 edit workflow)
Common error patterns (quick reference):
| Error | Cause | Fix |
|---|---|---|
Move out of range: X Y Z [step] |
Nozzle would exceed axis limit; often probe offset not accounted in calibration coords | Reduce calibrate_end_x / mesh_max by abs(probe.x_offset) |
Must home axis first |
Axes not homed before move command | Run G28 |
Endstop stepper_x still triggered |
Endstop stuck or wiring fault | Check QUERY_ENDSTOPS, check endstop pin polarity |
Unable to read tmc uart ... IFCNT |
TMC UART comms failure | Check motor power and UART wiring; power cycle |
TMC reports error: ... OvertempError |
TMC driver too hot | Reduce run_current, improve cooling |
TMC reports error: ShortToGND |
Shorted motor wire | Check motor wiring |
TMC reports error: Undervoltage |
PSU voltage dip | Check PSU and wiring connections |
Heater extruder not heating at expected rate |
PID tuning needed or heater/sensor issue | Run PID_CALIBRATE HEATER=extruder TARGET=200 |
Probe triggered prior to movement |
BLTouch in wrong state or z_offset too high | Run BLTOUCH_DEBUG COMMAND=reset then re-home |
Timeout on connect |
Moonraker not running or wrong IP | Verify printer IP and that Moonraker is running |
Lost communication with MCU |
USB disconnect or firmware crash | Run FIRMWARE_RESTART; check USB cable |
Phase 7: Config Section Reference
Use references/config_sections.md for the complete parameter reference.
Key sections and their most commonly tuned parameters:
[printer]
kinematics: cartesian # cartesian|corexy|corexz|delta|deltesian|polar
max_velocity: 300 # mm/s — runtime tunable via SET_VELOCITY_LIMIT
max_accel: 7000 # mm/s² — runtime tunable
max_z_velocity: 15 # mm/s (cartesian only)
max_z_accel: 100 # mm/s² (cartesian only)
minimum_cruise_ratio: 0.5 # 0.0–1.0, reduces top speed of short moves
square_corner_velocity: 5.0 # mm/s, higher = less deceleration at corners
[stepper_x/y/z]
rotation_distance: 40 # mm per full motor rotation
microsteps: 16 # 8|16|32|64|128
position_min: 0 # soft limit minimum
position_max: 246 # soft limit maximum — CRITICAL for range checks
position_endstop: 0 # endstop position (must match position_min or position_max)
homing_speed: 80 # mm/s
[extruder]
rotation_distance: 7.687 # mm per motor rotation (direct drive ~7-8, bowden ~20-40)
nozzle_diameter: 0.400
pressure_advance: 0.04 # 0 = disabled; typical range 0.02–0.12 for direct
pressure_advance_smooth_time: 0.04
max_extrude_cross_section: 5 # max mm² cross section (4 × nozzle_diameter² is safe default)
[bltouch] / [probe]
x_offset: -62 # probe X position relative to nozzle (negative = left of nozzle)
y_offset: -12 # probe Y position relative to nozzle (negative = in front)
# z_offset: stored in SAVE_CONFIG block
samples: 3 # number of probe samples
samples_result: median # average|median
sample_retract_dist: 5.0
samples_tolerance: 0.01 # max deviation between samples (mm)
samples_tolerance_retries: 3
[bed_mesh]
mesh_min: 60, 30 # PROBE coordinates (not nozzle!)
mesh_max: 170, 220 # PROBE coordinates
probe_count: 5, 5 # grid points per axis
algorithm: bicubic # lagrange (≤3×3) | bicubic (≥4×4 recommended)
fade_start: 1 # mm height to start fading mesh correction
fade_end: 10 # mm height where mesh correction reaches zero (0=disabled)
[axis_twist_compensation]
calibrate_start_x: 20 # PROBE X coordinate — nozzle = start_x - x_offset
calibrate_end_x: 183 # PROBE X coordinate — nozzle = end_x - x_offset
calibrate_y: 117.5 # PROBE Y coordinate — nozzle = calibrate_y - y_offset
# Rule: nozzle must be within [position_min, position_max]
# Formula: calibrate_end_x <= position_max + x_offset (when x_offset < 0)
[safe_z_home]
home_xy_position: 108.5, 117.5 # NOZZLE position for Z homing (not probe!)
speed: 120
z_hop: 10
z_hop_speed: 5
[tmc2209 stepper_x]
run_current: 0.750 # Amps RMS — start at 70% rated current
hold_current: 0.500 # Optional — Klipper docs recommend omitting
stealthchop_threshold: 999999 # 999999=always stealthChop; 0=always spreadCycle
interpolate: True # micro-step interpolation (small positional error)
driver_SGTHRS: 255 # stallGuard threshold for sensorless homing (if used)
[input_shaper]
shaper_type_x: 3hump_ei # mzv|ei|2hump_ei|3hump_ei|zv|zvd
shaper_freq_x: 66.2 # Hz — from SHAPER_CALIBRATE
shaper_type_y: ei
shaper_freq_y: 45.0
[firmware_retraction]
retract_length: 0.5 # mm — direct drive: 0.4–1.0; bowden: 4–7
retract_speed: 60 # mm/s
unretract_extra_length: 0
unretract_speed: 60
Moonraker API Quick Reference
Base URL: http://<IP>:7125
| Method | Endpoint | Purpose |
|---|---|---|
| GET | /printer/info |
Klipper state, version, hostname |
| GET | /server/files/config/printer.cfg |
Read printer.cfg |
| GET | /server/files/list?root=config |
List all config files |
| POST | /server/files/upload (multipart) |
Upload/overwrite a config file |
| POST | /printer/firmware_restart |
Firmware restart (apply config changes) |
| POST | /printer/gcode/script |
Send GCode command (JSON body: {"script":"..."}) |
| GET | /printer/objects/list |
List all queryable printer objects |
| GET | /printer/objects/query?<obj>=<fields> |
Query live printer state |
| GET | /printer/query_endstops/status |
Endstop states |
| POST | /printer/gcode/script {"script":"SAVE_CONFIG"} |
Persist calibration data |
| GET | /server/info |
Moonraker version, registered components |
| POST | /machine/reboot |
Reboot the host (Pi) |
| POST | /machine/shutdown |
Shutdown the host |
File Upload (curl)
curl -X POST "http://<IP>:7125/server/files/upload" \
-F "root=config" \
-F "file=@/path/to/printer.cfg;filename=printer.cfg"
GCode Send (curl)
curl -X POST "http://<IP>:7125/printer/gcode/script" \
-H "Content-Type: application/json" \
-d '{"script": "G28"}'
Object Query (curl)
curl "http://<IP>:7125/printer/objects/query?extruder&heater_bed&toolhead"
Platform Notes
The AI performs all config fetching, parsing, and editing inline using curl (available
on both Windows and Linux) and direct text analysis. The scripts in scripts/ are provided
as reference implementations and work on Linux/macOS (require python3). On Windows,
the AI executes the equivalent logic directly — do not rely on the shell scripts.
When running on the Klipper host directly (via SSH), the scripts work without modification.
File Structure
klipper-manager/
├── SKILL.md # This file
├── references/
│ ├── config_sections.md # Full parameter reference for all config sections
│ ├── gcodes.md # All supported G-codes and extended commands
│ ├── troubleshooting.md # Error patterns → causes → fixes
│ └── moonraker_api.md # Full Moonraker API reference
├── scripts/
│ ├── fetch_config.sh # Fetch printer.cfg from Moonraker
│ ├── upload_config.sh # Upload modified config
│ ├── send_gcode.sh # Send a GCode command
│ ├── query_status.sh # Query printer status objects
│ └── diagnose.sh # Full diagnostic run
└── state/
└── printer_context.json # Persisted printer state (auto-created)
Base directory: file:///C:/Users/santi/.config/opencode/skills/klipper-manager