How-to
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.
Edited by 3D Printeray EditorsPublished Last verified 3 min read
In this section: Klipper macros(19)
On this page (7)

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
- Enable RESPOND. Add an empty
[respond]section toprinter.cfg. Klipper only registersRESPONDwhen that section exists. - Write the prompt macro. Start it with
action:prompt_begin, addaction:prompt_textlines and buttons, and end withaction:prompt_show. - 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. - Restart and test. Run
RESTARTto 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_PRINTCall 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, orprompt_showwas never sent. - Text or a button is cut short: Klipper reads
#inprinter.cfgand;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
- Mainsail documentation, Macro prompts (accessed October 10, 2026)
- Klipper documentation, G-Codes (accessed October 10, 2026)
- Klipper documentation, Configuration reference (accessed October 10, 2026)
- Klipper documentation, Command templates (accessed October 10, 2026)
- Klipper source, pause_resume.py (accessed October 10, 2026)
- Klipper source, gcode.py (accessed October 10, 2026)
- Klipper source, configfile.py (accessed October 10, 2026)
- Mainsail source, MacroPromptButton.vue (accessed October 10, 2026)
- Mainsail source, printer store getters (accessed October 10, 2026)
- Fluidd documentation, Macros (accessed October 10, 2026)
- Fluidd release notes, v1.27.0 (accessed October 10, 2026)
- Fluidd source, console store actions (accessed October 10, 2026)