What Klipper macros can do

How to ask for user input in a Klipper macro

Klipper has no command that stops a macro to wait for a reply. Mainsail and Fluidd fill the gap with prompt dialogs that a macro opens and the buttons answer.

Published · Last verified

The front of a Voron printer with a small LCD status display and control knob
Photo: disinterpreter, CC BY-SA 2.0

To get user input in a Klipper macro, open a prompt dialog: send RESPOND TYPE=command MSG="action:prompt_begin <title>", add text and buttons, then action:prompt_show. Mainsail (v2.9.0 or newer) and Fluidd (v1.27.0 or newer) draw the dialog, and each button runs the G-code you assign to it.

Can a Klipper macro ask the user for input?

Yes, through the web interface. Klipper has no blocking input command, and its G-code reference lists no M0 or M1. A macro can print action:prompt_* messages with RESPOND TYPE=command, which Mainsail and Fluidd turn into a dialog with buttons. Each button runs G-code, usually another macro, which carries out the choice.

The macro that opens the dialog keeps going. Klipper evaluates a macro “in entirety and only then” runs its commands, so lines after action:prompt_show run without waiting. Put whatever depends on the answer in the button’s macro.

How to show a prompt dialog from a Klipper macro

  1. Enable RESPOND. Add an empty [respond] section to printer.cfg. Klipper only registers RESPOND when that section exists.
  2. Write the prompt macro. Start it with action:prompt_begin, add action:prompt_text lines and buttons, and end with action:prompt_show.
  3. Write one macro per button. Each one closes the dialog with action:prompt_end, then does its job. Clicking a button does not close the dialog in either interface.
  4. Restart and test. Run RESTART to reload the config, then type the prompt macro’s name in the console.

This prompt asks which material is loaded and heats the nozzle to match:

[respond]

[gcode_macro PICK_MATERIAL]
description: Ask which material is loaded, then heat for it
gcode:
    RESPOND TYPE=command MSG="action:prompt_begin Load filament"
    RESPOND TYPE=command MSG="action:prompt_text Which material is in the extruder?"
    RESPOND TYPE=command MSG="action:prompt_button_group_start"
    RESPOND TYPE=command MSG="action:prompt_button PLA|_HEAT_FOR TEMP=210|primary"
    RESPOND TYPE=command MSG="action:prompt_button PETG|_HEAT_FOR TEMP=240|primary"
    RESPOND TYPE=command MSG="action:prompt_button ABS|_HEAT_FOR TEMP=250|primary"
    RESPOND TYPE=command MSG="action:prompt_button_group_end"
    RESPOND TYPE=command MSG="action:prompt_footer_button Close|_PROMPT_CLOSE"
    RESPOND TYPE=command MSG="action:prompt_show"

[gcode_macro _HEAT_FOR]
gcode:
    {% set temp = params.TEMP|default(210)|int %}
    RESPOND TYPE=command MSG="action:prompt_end"
    M109 S{temp}
    RESPOND MSG="Nozzle at {temp} C. Feed the filament."

[gcode_macro _PROMPT_CLOSE]
gcode:
    RESPOND TYPE=command MSG="action:prompt_end"

The temperatures are examples, so set your filament’s values. TEMP=210 after the pipe passes a value to the button’s macro (macro parameters covers reading it). Names starting with _ keep the helpers off the macro panel in both interfaces.

Klipper macro prompt commands

Send each command as RESPOND TYPE=command MSG="action:...". TYPE=command adds the // prefix both interfaces watch for.

Command What it does Fluidd
prompt_begin <title> Starts a new prompt with this headline Yes
prompt_text <text> Adds a line of text Yes
prompt_button <label>|<gcode>|<color> Adds a button; G-code and color are optional Yes
prompt_button_group_start / _end Puts the buttons between them on one row Ignored
prompt_footer_button <label>|<gcode>|<color> Adds a button to the dialog footer Yes
prompt_show Opens the dialog Yes
prompt_end Closes it Yes

Mainsail’s colors are primary, secondary, info, warning and error. A button with no G-code runs its label as the command. Fluidd’s prompt code skips the group lines and stacks every button on its own row.

How to make a Klipper macro wait for input

During a print, pause it and let the buttons resume or cancel. PAUSE stops Klipper reading the print file, but the macro that called it carries on: lines after PAUSE in the same macro still run. After PAUSE, put only the prompt.

[gcode_macro CHECK_PLATE]
description: Hold the print until the plate is confirmed
gcode:
    PAUSE
    RESPOND TYPE=command MSG="action:prompt_begin Check the build plate"
    RESPOND TYPE=command MSG="action:prompt_text Is the plate clean and seated?"
    RESPOND TYPE=command MSG="action:prompt_footer_button Cancel|_PLATE_CANCEL|error"
    RESPOND TYPE=command MSG="action:prompt_footer_button Start|_PLATE_OK|primary"
    RESPOND TYPE=command MSG="action:prompt_show"

[gcode_macro _PLATE_OK]
gcode:
    RESPOND TYPE=command MSG="action:prompt_end"
    RESUME

[gcode_macro _PLATE_CANCEL]
gcode:
    RESPOND TYPE=command MSG="action:prompt_end"
    CANCEL_PRINT

Call CHECK_PLATE on its own line in your slicer’s start G-code, or as the last line of PRINT_START. Any command after it inside PRINT_START runs before anyone clicks. RESUME returns the toolhead to the position captured at the pause. If your PAUSE macro parks the head (pause and resume macros), the head moves before the dialog opens.

Outside a print, PAUSE holds nothing, because there is no print file to stop. A standalone macro has to hand its remaining steps to the buttons. To wait on heaters, moves or a timer instead of a person, see waiting in a Klipper macro.

Taking input as macro parameters

If you know the value before the macro runs, skip the dialog and pass a parameter: _HEAT_FOR TEMP=240 from the console or the slicer, read inside the macro as params.TEMP. Parameters need no interface support.

Why the prompt does not appear

  • Unknown command:"RESPOND": the [respond] section is missing, or Klipper has not restarted since you added it.
  • No dialog, but the console shows // action:prompt_... lines: the interface is older than Mainsail v2.9.0 or Fluidd v1.27.0, or prompt_show was never sent.
  • Text or a button is cut short: Klipper reads # in printer.cfg and ; on any G-code line as the start of a comment, even inside quotes. Keep both characters out of prompt text.
  • A button command breaks: a second pair of double quotes inside MSG="..." breaks the quoting. Point the button at a helper macro instead of nesting quoted commands.
  • The dialog stays open: the button’s macro never sent action:prompt_end.

Sources

  1. Mainsail documentation, Macro prompts (accessed October 10, 2026)
  2. Klipper documentation, G-Codes (accessed October 10, 2026)
  3. Klipper documentation, Configuration reference (accessed October 10, 2026)
  4. Klipper documentation, Command templates (accessed October 10, 2026)
  5. Klipper source, pause_resume.py (accessed October 10, 2026)
  6. Klipper source, gcode.py (accessed October 10, 2026)
  7. Klipper source, configfile.py (accessed October 10, 2026)
  8. Mainsail source, MacroPromptButton.vue (accessed October 10, 2026)
  9. Mainsail source, printer store getters (accessed October 10, 2026)
  10. Fluidd documentation, Macros (accessed October 10, 2026)
  11. Fluidd release notes, v1.27.0 (accessed October 10, 2026)
  12. Fluidd source, console store actions (accessed October 10, 2026)