One-line auto-installer for KAMP on the Creality K2. Skip the manual patch-and-pray.
KAMP (Klipper Adaptive Meshing & Purging) — Creality K2 fork
A fork of kyleisah/Klipper-Adaptive-Meshing-Purging with the small amount of extra glue Creality K2 printers need to make KAMP actually work.
❤️ Enjoying KAMP-K2? Free forever (GPL v3) — if it saved you some K2 mesh-fighting, buy me a coffee or tip BTC:
bc1q4tlvaufnaefshdjjuxm5xkcrdazefhap52hdja. No obligation, bug reports help just as much.Looking for upstream KAMP's own readme? It's preserved as README_KAMP_UPSTREAM.md.
Need help? Visit my site, we have a huge help section dedicated to the Creality K2 https://harktech.co.uk
Creality's K2 firmware does two things that break upstream KAMP out of the box (on the CR0CN200400C10 board — K2, K2 Combo, K2 Pro). K2 Plus has a half-implemented Creality adaptive mesh on a different board but users report it's unreliable; this fork replaces that too.
prtouch_v3_wrapper.so hijacks BED_MESH_CALIBRATE with a non-adaptive implementation that ignores MESH_MIN / MESH_MAX / PROBE_COUNT and crashes with IndexError when those are passed. KAMP relies on the upstream Klipper handler being present, so KAMP calls fail silently or blow up.master-server daemon independently fires G29 and BED_MESH_CALIBRATE_START_PRINT during print prep, outside of any slicer start-gcode. Those fire before KAMP can run and triggers a stock full-bed mesh every time.change_filament_gcode template drops Z to 0 immediately after LINE_PURGE at print start. The template uses {z_after_toolchange}, which is 0 before any layer has printed, so the nozzle scrapes from the post-purge position diagonally across the bed to the first print object. This is invisible in the slicer (it only manifests on first-print tool activation) and the upstream KAMP Line_Purge.cfg ends with a hardcoded 0.4 mm hop that isn't enough to escape it.KAMP-K2 fixes all three:
extras/restore_bed_mesh.py — a small Klipper extras module that re-registers the upstream bed_mesh.BedMeshCalibrate.cmd_BED_MESH_CALIBRATE handler, wrapping it with a guard that requires MESH_MIN / MESH_MAX bounds to run. Bare calls (from master-server) are no-ops. KAMP-aware: detects KAMP's rename_existing: _BED_MESH_CALIBRATE and overrides the inner handler so KAMP stays the user-facing entry point.G29 and BED_MESH_CALIBRATE_START_PRINT are replaced with no-op macros that emit a fake [G29_TIME]Execution time: 0.0 response so master-server's print-prep sequence is satisfied without actually running a mesh. The real mesh runs inside START_PRINT where KAMP has slicer metadata available.START_PRINT patches: a call to bare BED_MESH_CALIBRATE (which KAMP wraps with adaptive bounds) and a LINE_PURGE call are inserted in the right places relative to the K2's CFS-specific nozzle clean and prime moves.Line_Purge.cfg Z-protection (v1.1.0): a new purge_z_hop variable in KAMP_Settings.cfg (default 2.0 mm) controls the post-purge clearance. LINE_PURGE applies SET_GCODE_OFFSET Z=purge_z_hop at the end of the purge so Orca's subsequent G1 Z0 lands safely at the hop height instead of the bed. A G92 override (rename_existing: G92.1) clears the offset on the slicer's first post-purge G92 E0 — emitted in the layer-change block, between the bad Z=0 line and the first real layer Z move — so the first-layer height is unaffected. No slicer config changes needed.This fork modifies upstream KAMP's Line_Purge.cfg and KAMP_Settings.cfg to add the Z-protection above; Adaptive_Meshing.cfg and Voron_Purge.cfg are unchanged.
Open PowerShell (not cmd.exe) and paste:
iwr -useb https://raw.githubusercontent.com/grant0013/KAMP-K2/main/bootstrap.ps1 | iex
The script checks for Python (prompts to install if missing), downloads the repo, installs paramiko, asks for your printer's IP, and runs the installer. No manual SSH required.
Open a terminal and paste:
curl -fsSL https://raw.githubusercontent.com/grant0013/KAMP-K2/main/install.sh | bash
Same flow as the Windows one-liner: checks for Python 3.8+ (prompts you how to install it if missing), creates an isolated venv, installs paramiko, clones the repo into ~/KAMP-K2, asks for your printer's IP, and runs the installer. The venv sidesteps PEP 668 ("externally-managed-environment") errors on modern macOS / Ubuntu 23.04+ / Debian 12+ without needing --break-system-packages.
Non-interactive form (for scripts / re-runs):
~/KAMP-K2/install.sh --host 192.168.1.42
~/KAMP-K2/install.sh --host 192.168.1.42 --revert
If you'd rather not run the installer:
git clone https://github.com/grant0013/KAMP-K2
cd KAMP-K2
python3 -m venv .venv && .venv/bin/pip install paramiko
.venv/bin/python install_k2.py --host 192.168.x.x
Replace 192.168.x.x with your printer's IP. The installer uses the Creality stock root password (creality_2024) by default; override with --password MYPASS if yours has been changed.
See docs/INSTALL_K2.md for the step-by-step the installer performs (useful if you want to do it manually, or understand what's being changed).
Two different boards in the K2 family behave differently:
| Printer | Board | Stock adaptive mesh? | KAMP-K2 needed? |
|---|---|---|---|
| K2 / K2 Combo / K2 Pro | CR0CN200400C10 (F021) |
No (no forced_leveling toggle in printer.cfg, wrapper doesn't support adaptive bounds) |
Yes — this is the only option |
| K2 Plus | CR0CN240319C13 (F008) |
Yes, but off by default and forum-reported unreliable | Optional alternative; more maintainable than Creality's flaky toggle |
| K1 / K1C / K1 Max | CR4CU220812S* | No | Should work (same prtouch_v3_wrapper + master-server architecture); untested — please file an issue if you try it |
| K1 SE | CR4CU220812S12 | No | Unknown (wrapper may be prtouch_v2; minor path change in installer probably needed) |
| Non-Creality Klipper printer | — | — | Don't use this fork — use upstream KAMP directly; you don't have a wrapper to bypass |
Adaptive line purging (LINE_PURGE) is not available in any Creality K-series stock firmware. Even K2 Plus owners with Creality's built-in adaptive mesh working get no purge-line adaptation out of the box. KAMP-K2 brings both features on every variant it supports.
Tested on my K2 Combo (CR0CN200400C10, firmware V1.1.4.1, Klipper 09faed31-dirty).
| Slicer | Status | Notes |
|---|---|---|
| OrcaSlicer | Recommended / fully supported | Free, emits EXCLUDE_OBJECT_DEFINE out of the box, placeholder syntax matches KAMP-K2's docs. All testing done here. |
| Bambu Studio | Expected to work | Same codebase as Orca, same placeholder syntax. Untested. |
| PrusaSlicer / SuperSlicer | Should work | Emits object metadata via "Label objects". Variable names differ slightly (see below). Untested. |
| Creality Print | Partial / not recommended | Emits EXCLUDE_OBJECT_DEFINE correctly (tick "Exclude objects" + "Label objects" under G-code output), so KAMP's adaptive mesh will run. HOWEVER: CP uses its own placeholder syntax that's incompatible with the custom start-gcode shown below, and its default start-gcode triggers Creality's built-in pre-print mesh sequence in addition to KAMP's — you end up with one full mesh + one adaptive mesh per print, wasting probe time. KAMP-K2 is primarily developed and tested against Orca. If you want full benefit, switch slicer. |
The rest of this setup section assumes OrcaSlicer. If you use CP anyway, leave its default start-gcode alone — don't paste the Orca-specific lines below. KAMP will still run adaptively inside
START_PRINT, you'll just also get CP's full mesh and corner purge on top.
Printer Settings → Machine G-code → Machine start G-code — replace the default with exactly these five lines:
START_PRINT EXTRUDER_TEMP=[nozzle_temperature_initial_layer] BED_TEMP=[bed_temperature_initial_layer_single]
T[initial_no_support_extruder]
LINE_PURGE
M204 S2000
M83
Forgot what to paste? The installer auto-prints this block on fresh installs. To regenerate it any time:
sh python3 ~/KAMP-K2/slicer_gcode.py # Orca (default) python3 ~/KAMP-K2/slicer_gcode.py --board F008 # K2 Plus (mesh max 345,345)Why these exact lines, in this order: -
START_PRINTruns heating, homing, adaptive mesh, nozzle clean. Does not load filament (that's slicer-side on K2). -T[initial_no_support_extruder]triggers the CFS (or direct-drive loader) to actually pull filament to the nozzle. -LINE_PURGEmust come after T<n> — if it runs before, there's no filament at the nozzle yet and you get an empty purge followed by an un-purged start (reported by issue #1). -M204 S2000+M83— accel limit + relative extrusion. Anything beyond these is usually the slicer's default fixed purge line, which wastes filament now that KAMP is doing an adaptive one.
Print Settings → Others → Bed mesh (match your [bed_mesh] section in printer.cfg):
- Bed mesh min: 5, 5
- Bed mesh max: 255, 255 on K2/K2 Combo (260³), or 345, 345 on K2 Plus (350³) — read the mesh_max: line in your printer.cfg to be sure
- Probe point distance: 50, 50
- Mesh margin: 5
Print Settings → Others → Output options: make sure Label objects is enabled (this writes the EXCLUDE_OBJECT_DEFINE lines that KAMP reads).
You do NOT need to pass MESH_MIN / MESH_MAX / PROBE_COUNT — KAMP figures them out from the loaded gcode's exclude_object metadata.
To skip the adaptive mesh entirely on a specific slice (e.g. a calibration cube you don't care about), add MESH=0 to the START_PRINT call:
START_PRINT EXTRUDER_TEMP=[...] BED_TEMP=[...] MESH=0
Any slicer that supports [exclude_object] / object-labeled gcode output will work. PrusaSlicer, SuperSlicer, and Bambu Studio all do. The only requirement is that the EXCLUDE_OBJECT_DEFINE lines appear in the file before the START_PRINT call, so printer.exclude_object.objects is populated by the time KAMP reads it. OrcaSlicer does this by default; other slicers vary.
The slicer_gcode.py helper prints a ready-to-paste block for each supported slicer, with the correct placeholder syntax and paste location:
python3 slicer_gcode.py --slicer bambu # Bambu Studio (same as Orca)
python3 slicer_gcode.py --slicer prusa # PrusaSlicer
python3 slicer_gcode.py --slicer super # SuperSlicer
python3 slicer_gcode.py --list # show all + differences
No paramiko needed — pure stdlib, runs under any Python 3.
After running the installer, open your printer's gcode console and slice a small test print. You should see something like:
// Algorithm: bicubic.
// Default probe count: 11,11.
// Adapted probe count: 4,4.
// Default mesh bounds: (5, 5), (255, 255).
// Adapted mesh bounds: (106.0, 39.0), (154.0, 221.0).
// KAMP adjustments successful. Happy KAMPing!
// KAMP purge starting at 115.0, 29.0 and purging 30.0mm of filament, requested flow rate is 12.0mm3/s.
The probe should then walk only the area covering your printed objects.
In klippy.log, the override should announce itself on every Klippy restart:
[INFO] bed_mesh_override: _BED_MESH_CALIBRATE re-registered to guarded upstream
(KAMP mode; bare calls are no-ops; MESH_MIN/MAX required to run)
KAMP-K2 does not enable upstream KAMP's Smart_Park.cfg. The K2 has its own BOX_GO_TO_EXTRUDE_POS macro (part of the CFS filament-change flow) that already parks the nozzle at a reasonable location during print prep. Adding Smart_Park on top would just override that with a parking location near the first layer — which the printer was about to move to anyway. If you have a strong reason to enable it, uncomment the line in KAMP_Settings.cfg by hand after install.
Run the installer with --revert (not yet implemented — see Issues) or restore the backup that the installer makes at:
/mnt/exUDISK/.system/kamp_k2_backup_<timestamp>/ (on printers with the external SSD), or/mnt/UDISK/printer_data/config/backups/kamp_k2_<timestamp>/ (without SSD)Then remove extras/restore_bed_mesh.py, remove [restore_bed_mesh] and [include KAMP/KAMP_Settings.cfg] from printer.cfg, and restart Klippy.
If you want adaptive meshing to run fewer probe points on small parts (faster mesh time, same first-layer quality), see docs/tuning.md. Default ceiling on most K2s is probe_count: 11,11 — the doc explains when and why dropping it to 7,7 (Creality's own default) or lower is worth doing, and when it isn't.
probe_count tuning and MESH=0 skip-mesh flagK2-Screws-Tilt — brings Klipper's SCREWS_TILT_CALCULATE helper to the K2 family. Uses your existing strain-gauge probe to tell you "front-left: turn 1/4 CW" for manual bed-screw levelling. Same one-click Windows installer, same backup/revert UX. Confirmed on K2 Combo.
Built on top of: - Klipper — Kevin O'Connor and contributors - kyleisah/Klipper-Adaptive-Meshing-Purging — the upstream KAMP project, unchanged in this fork - pellcorp/creality — early K1 / K2 reverse-engineering groundwork
Hark Tech, the maintainer of this project, runs a large free Creality K2 help library covering Klipper, input shaper, pressure advance, bed mesh, slicer profiles and the common K2 failure modes. Stuck on something specific? Get in touch and ask: remote K2/Klipper help is available, priced per job.
Hark Tech also runs a UK mail-in 3D print service (instant quote from an STL, orders from £6, full rate card) and a gadget repair service from the same bench.
GPL v3, matching upstream KAMP and Klipper. See LICENSE.md.
If you’d rather have someone else do the config work, I can set up Klipper, KAMP and adaptive meshing on your printer by post. Mail it to the workshop, I’ll tune it, you get it back working.