Construction

M-Code Reference by Controller (Haas, LinuxCNC, GRBL, Marlin)

CNC M-codes (M00–M99 and up) for Haas mills and lathes, LinuxCNC, GRBL and Marlin, side by side, with the codes that mean different things on each control.

M-codes are machine functions that do not command axis motion. The core set is the same on most CNC controls: M00 program stop, M01 optional stop, M03 / M04 / M05 spindle clockwise / counter-clockwise / stop (speed in rpm from the S word), M06 tool change, M08 coolant on, M09 coolant off and M30 program end and reset. Beyond that the controls differ: Grbl has no M6 tool change and ignores M1; Haas uses M07 for shower coolant; and on Marlin 3D printers M30 deletes a file from the SD card while M104/M109 set the hotend temperature instead of working a probe arm, as they do on a Haas mill. Below: the four controls side by side, then the full Haas mill and lathe, LinuxCNC and Grbl lists from each maker's documentation. To see what a program's M-codes do line by line, paste it into the G-code Explainer & Simulator.

Core M-codes (Haas and LinuxCNC agree)

CodeNameWhat it does
M00Program stopStops the program; Cycle Start continues from the next block. Haas M00 also stops the axes, spindle and coolant.
M01Optional stopSame as M00, but only when the Optional Stop switch is on.
M02Program endEnds the program.
M03Spindle clockwiseStarts the spindle forward at the S speed (S5000 = 5,000 rpm).
M04Spindle counter-clockwiseStarts the spindle in reverse at the S speed.
M05Spindle stopStops the spindle (Haas waits for it to stop).
M06Tool changePuts the tool selected by the T word in the spindle, e.g. M06 T12 (Haas), or T12 M6 (LinuxCNC).
M08Coolant onFlood coolant on.
M09Coolant offTurns coolant off.
M19Orient spindleTurns the spindle to a fixed angle between 0 and 360°.
M30Program end and resetEnds the program and makes it ready to run again from the top.
M98Subprogram callCalls another program (Haas: P = program number, L = 1–99 repeats).
M99Subprogram returnReturns to the calling program (Haas: in a main program it loops back to the start).

Numbers that go with M-codes

WordUsed withMeaningUnit
SM03 / M04Spindle speed (Haas: S5000 = 5,000 rpm)rpm
TM06Tool number (LinuxCNC: the pocket number in the carousel)number
PM19 (Haas)Orient angle, whole degrees 0–360degrees (°)
RM19 (Haas, LinuxCNC)Orient angle; Haas allows two decimals (0.00–360.00)degrees (°)
QM19 (LinuxCNC)Time to wait for the spindle to orient before an errorseconds (s)
PM08 (Haas variable flow)P0 / P1 / P2 = low / normal / high pressure, pump at 50 / 60 / 80Hz
PM97 / M98 (Haas)N line number (M97) or program number (M98) to callnumber
LM97 / M98 (Haas)Number of times to repeat the call, 1–99count

Same code, four controllers

CodeHaas millLinuxCNCGrbl 1.1Marlin 2.x
M0Stop programPausePause (feed hold)Stop, wait for user
M1Optional stopOptional pauseIgnoredSame as M0 (deprecated)
M2Program endEnd, reset modesEnd, reset modesNot listed
M3 / M4 / M5Spindle fwd / rev / stopSpindle CW / CCW / stopSpindle CW / CCW / stopSpindle or laser (build option)
M6Tool changeTool changeNot supported (error:20)Not listed; T0–T7 select a tool
M7Shower coolantMist coolantMist (compile option)Mist (build option)
M8Coolant onFlood onFlood onFlood (build option)
M9Coolant offMist and flood offMist and flood offCoolant off (build option)
M19Orient spindleOrient spindleNot supportedNot listed
M30End and resetEnd, pallet change, resetSame as M2Delete SD file
M48Check pallet programOverrides onNot supportedProbe repeatability test
M97Local subprogramNot listedNot supportedNot listed
M98 / M99Sub call / returnSub call / returnNot supportedNot listed
M104Probe arm extendUser M-code rangeNot supportedSet hotend temp.
M109Interactive inputUser M-code rangeNot supportedWait for hotend temp.

Where the controls differ

  • M6 tool change. Haas: M06 stops the spindle and coolant (including through-spindle coolant), moves Z to the tool-change position and orients the spindle by itself, so the program does not need M05, M09 or M19 first. LinuxCNC: the spindle stops, but "coolant will continue to flow during the tool change unless it has been turned off by an M9", and M6 does not change the tool length offset, so follow it with G43. With hal_manualtoolchange loaded, LinuxCNC stops and prompts the operator. Grbl rejects M6 with error:20. Marlin selects tools and extruders with T0–T7.
  • M8 / M9 coolant. On LinuxCNC and Grbl, M7 and M8 can both be on and M9 turns both off. On a Haas mill M07 is the optional shower coolant; M09 stops shower and standard coolant; and with the Variable Flow Coolant option, M08 P0 / P1 / P2 run the pump at 50 / 60 / 80 Hz (low, normal, high pressure). Through-spindle coolant is M88 / M89 on Haas mills.
  • M30 vs M2. Haas M30 stops the program, spindle and coolant (including TSC) and returns the cursor to the start; since Haas software 100.16.000.1041 it no longer cancels tool length offsets. LinuxCNC M2 and M30 both switch to MDI and reset work offset (G54), plane (G17), distance (G90), feed mode (G94), overrides (M48), cutter comp (G40), spindle (M5), motion (G1) and coolant (M9); M30 also exchanges pallet shuttles, and lines after either are not run. Grbl M2 and M30 reset G1, G17, G90, G94, G54, M5 and M9 but keep F, S and T. Marlin M30 deletes a named file from the SD card.
  • M1 optional stop. Grbl accepts M1 and ignores it (its source says "Optional stop not supported"). Marlin documents M1 as a deprecated alias of M0, and both are ignored without an LCD or the emergency parser.
  • M19 orient. Haas: P is whole degrees 0–360, R allows two decimals (M19 R123.45); a negative value orients to 0°. LinuxCNC: M19 R- Q- [P-], where R is the angle 0–360°, Q the seconds to wait for orientation, and P the direction (0 shortest, 1 clockwise, 2 counter-clockwise); it needs a spindle encoder.
  • One M-code per line. Haas allows one M-code per block and runs it at the end of the block. LinuxCNC allows up to four M words per line from different modal groups, and runs them in a fixed order (M6 before M3, before M7–M9, before the stop codes M0/M1/M2/M30/M60), not in the order written.
  • Codes above M99. LinuxCNC reserves M100–M199 for user-defined commands (scripts). Haas uses numbers above 100 for options (M104/M105 probe arm, M130 media display, M138/M139 spindle speed variation). Marlin uses them for printer functions (M104 hotend, M106 fan, M140 bed, M500 save settings). The same number can therefore do very different things.

Haas mill M-codes (full list)

CodeHaas mill function
M00Stop program
M01Optional program stop
M02Program end
M03Spindle forward
M04Spindle reverse
M05Spindle stop
M06Tool change
M07Shower coolant on
M08 / M09Coolant on / off (M08 Pn sets pump speed with the variable-flow option)
M10 / M11Engage / release 4th-axis brake
M12 / M13Engage / release 5th-axis brake
M16Tool change
M19Orient spindle (optional P and R values)
M21–M25Optional user M function with M-Fin
M29Set output relay with M-Fin
M30Program end and reset
M31Chip conveyor forward
M33Chip conveyor stop
M34Coolant increment
M35Coolant decrement
M36Pallet part ready
M39Rotate tool turret
M41 / M42Low / high gear override
M46Qn Pmm jump to line
M48Validate that the current program is appropriate for the loaded pallet
M50Pallet change sequence
M51–M55Set optional user M-codes
M59Set output relay
M61–M65Clear optional user M-codes
M69Clear output relay
M70 / M71Workholding clamp / unclamp
M73 / M74Tool air blast (TAB) on / off
M75Set G35 or G136 reference point
M78Alarm if skip signal found
M79Alarm if skip signal not found
M80 / M81Auto door open / close
M82Tool unclamp
M83 / M84Auto air gun on / off
M86Tool clamp
M88 / M89Through-spindle coolant on / off
M90 / M91Fixture clamp input on / off
M95Sleep mode
M96Jump if no input
M97Local subprogram call (P = N line number, L = 1–99 repeats)
M98Subprogram call (P = program number, L = 1–99 repeats)
M99Subprogram return or loop
M104 / M105Probe arm extend / retract
M109Interactive user input
M116 / M117Vise air chip blast on / off
M130 / M131Display media / cancel display media
M138 / M139Spindle speed variation on / off
M158 / M159Mist condenser on / off
M160Cancel active PulseJet
M161PulseJet continuous mode
M162PulseJet single-event mode
M163PulseJet modal mode
M180 / M181Auto window open / close
M199Pallet / part load or program end
M300APL / robot custom sequence

Haas lathe M-codes (full list)

CodeHaas lathe function
M00Stop program
M01Optional stop program
M02Program end
M03Spindle on forward
M04Spindle on reverse
M05Spindle stop
M08 / M09Coolant on / off
M10 / M11Chuck clamp / unclamp
M12 / M13Auto jet air blast on / off (optional)
M14 / M15Main spindle brake on / off (optional C axis)
M17Turret rotation forward
M18Turret rotation reverse
M19Orient spindle (optional)
M21Tailstock advance (optional)
M22Tailstock retract (optional)
M23Chamfer out of thread on
M24Chamfer out of thread off
M30End of program and reset
M31Chip auger forward (optional)
M33Chip auger stop (optional)
M35Parts catcher part-off position
M36Parts catcher on (optional)
M37Parts catcher off (optional)
M38 / M39Spindle speed variation on / off
M41 / M42Low / high gear (optional)
M43Turret unlock (service use only)
M44Turret lock (service use only)
M51–M56Turn on built-in M-code relay
M59Turn on output relay
M61–M66Turn off built-in M-code relay
M69Turn off output relay
M78Alarm if skip signal found
M79Alarm if skip signal not found
M85 / M86Automatic door open / close (optional)
M88 / M89High-pressure coolant on / off (optional)
M90 / M91Fixture clamp input on / off
M95Sleep mode
M96Jump if no signal
M97Local subprogram call
M98Subprogram call
M99Subprogram return or loop
M104 / M105Probe arm extend / retract (optional)
M109Interactive user input
M110Secondary spindle chuck clamp (optional)
M111Secondary spindle chuck unclamp (optional)
M112 / M113Secondary spindle air blast on / off (optional)
M114 / M115Secondary spindle brake on / off (optional)
M119Secondary spindle orient (optional)
M121–M126Built-in M-code relays with M-Fin
M129Turn on M-code relay with M-Fin
M130 / M131Display media / cancel display media
M133Live tool forward (optional)
M134Live tool reverse (optional)
M135Live tool stop (optional)
M138Spindle speed variation on
M139Spindle speed variation off
M143Secondary spindle forward (optional)
M144Secondary spindle reverse (optional)
M145Secondary spindle stop (optional)
M146 / M147Steady rest clamp / unclamp (optional)
M158 / M159Mist condenser on / off
M170 / M171Engage / release 4th-axis brake
M214 / M215Live tool brake on / off
M219Live tool orient (optional)
M299APL / part load / or program end
M300APL / robot custom sequence
M334 / M335P-Cool increment / decrement
M373 / M374Tool air blast (TAB) on / off
M388 / M389Through-spindle coolant on / off

Mill vs lathe on the same make

  • The Haas lathe list has no M06 and no M07; M10 / M11 are the chuck on a lathe but the 4th-axis brake on a mill; M12 / M13 are an air blast on a lathe but the 5th-axis brake on a mill; through-spindle coolant is M88 / M89 on a mill but M388 / M389 on a lathe, where M88 / M89 are high-pressure coolant.
  • Spindle speed variation is M138 / M139 on both, and the lathe also lists M38 / M39 for it.

LinuxCNC M-codes

CodeFunctionModal group
M0, M1Program pause; M1 only with the optional-stop switch on4 (stopping)
M2, M30Program end; M30 also exchanges pallet shuttles4 (stopping)
M60Pallet change pause4 (stopping)
M3, M4, M5Spindle CW, CCW, stop; $n picks the spindle, $-1 all spindles7 (spindle)
M6Tool change to the last T word6 (tool change)
M7, M8, M9Mist on, flood on (both may be on), both off8 (coolant)
M19Orient spindle (R angle, Q timeout s, P direction)7 (spindle)
M48, M49Enable / disable feed and spindle overrides9 (overrides)
M50Feed override control (P1 on, P0 off)—
M51Spindle speed override control—
M52Adaptive feed control—
M53Feed stop control—
M61Set current tool number without a tool change (Q)—
M62–M65Digital output on/off, synchronised with motion (M62/M63) or immediate (M64/M65)5 (I/O)
M66Wait on a digital or analog input5 (I/O)
M67, M68Analog output, synchronised / immediate5 (I/O)
M70–M73Save, invalidate, restore and auto-restore the modal state—
M98, M99Fanuc-style subprogram call and return—
M100–M199User-defined M-codes10 (user defined)

Grbl 1.1 M-codes

CodeGrbl behaviour
M0Program pause, using a feed hold; resume with ~ (cycle start).
M1Accepted and ignored.
M2, M30Program end: resets motion G1, plane G17, distance G90, feed mode G94, work offset G54, spindle M5 and coolant M9.
M3, M4, M5Spindle CW, CCW, stop; S sets the PWM output between $31 and $30 rpm. With laser mode ($32=1) power changes without stopping.
M7Mist coolant, only when compiled with ENABLE_M7.
M8, M9Flood coolant on; M9 turns off both M7 and M8.
M56Parking motion override, only in builds with parking and this option.
Anything elseerror:20 (unsupported command), including M6, M19, M48/M49 and M98/M99. See the GRBL error codes.

Marlin (3D printers): the M-codes that clash with CNC

  • Marlin uses M-codes mostly for printer functions: M104 / M109 hotend temperature (set / set and wait), M140 / M190 bed temperature, M106 / M107 fan, M82 / M83 absolute / relative extrusion, M84 steppers off, M500 / M501 / M502 / M503 save / load / reset / report settings. The full list with parameters is on the Marlin G-code and M-code reference.
  • M3 / M4 / M5 run a spindle or laser only when Marlin is built with spindle/laser support; M7 / M8 / M9 only with COOLANT_CONTROL. Without those build options they are not available.
  • M30 is "Delete SD file" and M48 is a Z-probe repeatability test, so CNC programs must not be sent to a printer unchanged.

Program end on each control

(Haas mill, from Haas's own G81 example)
G00 G90 Z1. M09     (Rapid retract, coolant off)
G53 G49 Z0 M05      (Z home, spindle off)
G53 Y0              (Y home)
M30                 (End program)
%

(LinuxCNC, from its G80 example)
G80                 (turn off canned cycle)
G0 X0               (rapid move home)
M2                  (program end)

(Grbl)
M5
M9
M30

Comments are written in ( ) because ";" ends the block on Haas and other Fanuc-style controls; LinuxCNC accepts both ( ) and ";" comments. Note Haas's one-M-code-per-line rule: M09 and M05 share their lines with G-codes, not with each other. Paste any of these into the simulator (LinuxCNC or Haas dialect) to see each line explained.

Sources

  • Haas Automation, Mill Operator's Manual — 18: Mill M-Codes and Lathe Operator's Manual — Lathe M-Codes (haascnc.com/service/online-operator-s-manuals/…), with the Haas code pages for M00, M01, M02, M03–M05, M06, M07, M08/M09, M19, M29, M30, M97, M98 and M99. haascnc.com blocks automated downloads, so the pages were read from Internet Archive copies captured between July 2024 and August 2025 (web.archive.org). Used for: both Haas lists, the one-M-code-per-block rule, M06, M07, M08 P0–P2, M19, M30 and subprogram details.
  • LinuxCNC Project, M-Codes and G-code Overview (modal groups, order of execution), linuxcnc.org/docs/html/gcode/m-code.html and …/overview.html, pages last updated 13 September 2026. Used for: the LinuxCNC list, modal groups, M2/M30 reset list, M6, M7–M9, M19, the four-M-words rule.
  • gnea/grbl, Grbl 1.1h source (grbl/gcode.c) and README "List of Supported G-Codes in Grbl v1.1" (github.com/gnea/grbl), 2019. Used for: the Grbl list, M1 ignored, M2/M30 reset, M9 behaviour, unsupported M-codes.
  • MarlinFirmware, Marlin G-code index (marlinfw.org/docs/gcode, source github.com/MarlinFirmware/MarlinDocumentation, downloaded 6 October 2026): pages for M0–M1, M3, M5, M7–M9, M30, M48, M104, M109. Used for: the Marlin column.
  • All sources were read on 6 October 2026. Fanuc's own manuals are not freely published, so "Fanuc-style" behaviour on this page is taken from Haas's documentation only; check your machine builder's manual for other controls.

Frequently asked questions

What is the difference between M02 and M30?

Both end the program. On Haas, M30 also stops the spindle and coolant and returns the cursor to the start of the program, and Haas calls it the most common way to end a program. On LinuxCNC, M2 and M30 both reset the modal state (G54, G17, G90, G94, G40, M5, M9, G1) and M30 also exchanges pallet shuttles. Grbl treats them the same.

What does M06 do?

M06 changes to the tool selected by the T word (M06 T12 loads tool 12). On a Haas mill it also stops the spindle and coolant, moves Z to the change position and orients the spindle. On LinuxCNC coolant keeps flowing unless M9 was given, and the tool length offset is not changed, so program G43 after M6. Grbl has no M6 (error:20).

What are M07, M08 and M09?

M08 turns flood coolant on and M09 turns coolant off. M07 is mist coolant on LinuxCNC, Grbl (a compile option) and Marlin, but shower coolant on a Haas mill. M09 switches off both M07 and M08 on LinuxCNC and Grbl, and on a Haas it stops shower and standard coolant.

Does M30 end the program on a 3D printer?

No. In Marlin, M30 deletes a file from the SD card, and Marlin's G-code index has no M2. Printer jobs normally end with heater, fan and stepper commands such as M104 S0, M140 S0, M107 and M84.

How many M-codes can be on one line?

Haas allows only one M-code per block, and all M-codes take effect at the end of the block. LinuxCNC allows up to four M words on a line, but not two from the same modal group; Grbl also rejects two from the same group (error:21).

Was this article helpful?