---
title: "M00 vs M01: Program Stop and Optional Stop Explained"
description: "M00 always stops the program; M01 stops only when the Optional Stop toggle is on. When to use each, what resumes after cycle start, and the full stop family."
url: https://gcodepractice.com/journal/m00-vs-m01-program-stop-and-optional-stop/
canonical: https://gcodepractice.com/journal/m00-vs-m01-program-stop-and-optional-stop/
author: "Lawrence Arya"
authorUrl: https://www.linkedin.com/in/vibecoding/
published: 2026-08-02
updated: 2026-08-02
category: "Code reference"
tags: ["m-code", "m00", "m01", "program-stop", "beginner", "setup"]
lang: en
---

# M00 vs M01: Program Stop and Optional Stop Explained

> **TL;DR** M00 is an unconditional program stop: the machine halts at that line every time and waits for cycle start, so it guards mandatory actions like part flips. M01 is an optional stop that only halts when the control's OPT STOP toggle is on, which makes it right for per-tool checks during setup that production later skips. Re-command spindle and coolant after any stop rather than trusting resume behavior, and end programs with M30.

M00 and M01 both stop a running program mid-cycle; the difference is who decides. M00 is an unconditional program stop: the machine halts at that line every single time, and waits for cycle start before continuing. M01 is an optional stop: it halts only if the operator has switched the control's Optional Stop function on; with the switch off, the control reads the line and sails straight past it. Programmers plant M00 where the program must never continue without a human action, like flipping a part over, and M01 where a stop is sometimes useful, like checking an insert after a heavy roughing pass on the first few parts of a run. Learn the pair together with M02 and M30, the end-of-program codes, and you have the complete stop family that appears in essentially every professional program you will ever read.

## What exactly does M00 do?

M00 stops everything the program is doing: axis motion halts, and on most controls the spindle and coolant stop too. The program pointer stays parked on the M00 line, the machine sits in a feed-hold-like state, and nothing moves until the operator presses cycle start. The [LinuxCNC M-code reference](https://linuxcnc.org/docs/html/gcode/m-code.html) describes it as a program pause that waits for the cycle start button, and that behavior is uniform across control families: Fanuc, Haas, Siemens, and hobby controls all treat M00 as a hard wait.

What happens to spindle and coolant on restart matters and differs by control. On many machines, modal states such as spindle on and coolant on resume automatically after cycle start; on others the operator must restart them manually, and a program that assumes the wrong behavior feeds a stationary tool into the part. The defensive habit is to re-command the spindle and coolant explicitly after any M00, one S word, one M03, one M08, so the program does not depend on what the control remembers. It is the same defensive logic as a safety block, and it costs two short lines. The subtleties of restarting from an arbitrary point, which an M00 stop often invites, are covered in [how to safely restart a CNC program from the middle](/journal/how-to-safely-restart-a-cnc-program-from-the-middle/).

Typical M00 uses are the ones where skipping the stop scraps the part or hurts someone: flip the part for op 2, remove chips before a critical finish pass, install a fixture clamp that would collide with an earlier toolpath, verify the first article before letting the machine continue. In all of those, the stop is part of the process, not an option, and that is the test for choosing M00.

## What exactly does M01 do, and where is the switch?

M01 executes exactly like M00 when, and only when, the Optional Stop toggle on the control is active. That toggle is a physical button or soft key labeled OPT STOP, M01, or Optional Stop, usually near single block and block delete on the operator panel. With the toggle off, the control treats M01 as a blank line. The line is always in the program; the operator decides at run time whether it means anything, which is what separates it from every other stop code.

That design gives M01 its role: stops you want during setup and proving, but not during production. A typical pattern places an M01 immediately after every tool change, so the setup person can run the job tool by tool, inspecting each operation's result with the machine paused, then hand the job to production where the toggle stays off and the same program runs uninterrupted. The same idea appears in [common mistakes to avoid during a CNC practical exam](/journal/common-mistakes-to-avoid-during-a-cnc-practical-exam/): proving out a program one stop at a time is standard professional practice, not a beginner crutch.

The classic M01 failure is silent: the operator believes the toggle is on, it is not, and the machine continues into a situation the stop was guarding. Because an ignored M01 looks identical to no code at all, nothing warns you. The discipline is to treat the toggle as part of setup state, checked before cycle start like the coolant valve, and never to guard a genuinely mandatory action with an M01. If skipping the stop can crash the machine or ruin the part every time, it must be M00; M01 guards only the stops that are optional by definition.

## The whole stop family side by side

| Code | Name | Stops when | Program pointer afterwards | Typical use |
| --- | --- | --- | --- | --- |
| M00 | Program stop | Always | Stays on the line; cycle start resumes | Part flip, mandatory inspection, chip clearing |
| M01 | Optional stop | Only if OPT STOP toggle is on | Same as M00 | Per-tool checks during setup and first articles |
| M02 | Program end | Always | Program ends; behavior varies by control | Legacy end-of-program |
| M30 | Program end and rewind | Always | Resets to the top, ready for the next part | Standard modern end-of-program |
| M60 | Pallet change and stop | Always (where supported) | Like M00 plus pallet exchange | Pallet machines, LinuxCNC |

Two notes on the family. M02 versus M30 is its own small confusion: both end the program, but M30 rewinds to the beginning so the next cycle start runs the next part, which is why modern programs end with M30 almost exclusively; the details connect to what happens when a program will not rewind, covered in [CNC machine stuck on M30 won't rewind](/journal/cnc-machine-stuck-on-m30-won-t-rewind/). And because M codes are the machine-function family, their exact behavior is the least standardized corner of G-code: the [Fanuc M-code list](https://www.helmancnc.com/fanuc-m-code-list/) is a good baseline, but the machine tool builder's own documentation always wins, especially for what resumes automatically after a stop.

## A program fragment that uses both correctly

```
O2001 (OP1 ROUGH AND FLIP)
G20 G90 G94 G17 G40 G80 (safety block)
T1 M06 (rough end mill)
S4500 M03
G00 X-0.6 Y0.0
G43 H1 Z0.1
M08
(...roughing passes...)
M09
M01 (optional: check insert wear during proving)
T2 M06 (finish end mill)
S6000 M03
M08
(...finish passes on top face...)
M09
M05
M00 (MANDATORY: flip part in vise, jaw 2 reference)
S6000 M03 (re-command spindle after stop)
M08 (re-command coolant after stop)
(...op 2 passes...)
M09
M05
M30
```

The structure tells the story. The insert check after roughing is an M01 because it matters during proving and the first parts of a run, then becomes a waste of cycle time once the process is stable; the operator retires it with a toggle instead of an edit. The part flip is an M00 because continuing without it machines the wrong side of the part every time, with no exception. And the lines after the M00 re-command spindle and coolant explicitly, so the resume behavior of this particular control never becomes part of the process. Comments state what the operator should do at each stop, which is a kindness to the 2 a.m. version of whoever runs this job; program comments and their syntax are covered in [how to add comments in G-code parentheses](/journal/how-to-add-comments-in-g-code-parentheses/).

## How the stop codes behave on different controls

The core meaning of M00 and M01 is as close to universal as anything in G-code, and the [general M-code conventions](https://en.wikipedia.org/wiki/Numerical_control) predate any current control brand. The differences live at the edges. Whether spindle and coolant restart automatically after cycle start varies by builder and even by parameter setting on the same control. Whether M00 is allowed to appear on a line with other commands varies: the safe style is M00 alone on its line, always. Hobby controls differ more: GRBL implements M0 and M1 (the leading zero is optional in most dialects), but many GRBL senders handle the pause on the sender side, and M1 support depends on a compile-time option, so a program moved from an industrial machine to a router may pause differently than expected.

There is also a human-factors difference worth knowing: on some controls, a program stop looks nearly identical to a feed hold on the screen. An operator walking up to a stopped machine should be able to tell which state it is in before touching anything, because the resume path differs. Reading the active state line on the control display, rather than guessing from the axes being stationary, is the habit that prevents pressing the wrong button.

A last edge case involves automation. On machines tended by bar feeders, pallet pools, or robots, unattended running is the whole point, and a forgotten M00 in a proven program stops the cell in the middle of the night with nobody there to press cycle start. Shops running lights-out audit their production programs for stop codes before releasing them, and some controls can be parameterized to alarm on M00 in specific modes. The mirror-image discipline also exists: some shops require an M00 before the first cut of any new program revision, forcing a human decision the first time changed code runs. Both practices treat stop codes as part of process design, which is exactly what they are.

## Bottom line: M00 commands a stop, M01 offers one

Use M00 for stops the process cannot survive skipping, part flips, mandatory inspections, anything where continuing unattended ruins the part or worse. Use M01 for stops that help during setup and first articles but would only waste cycle time in production, and remember its power switch lives on the operator panel, not in the program. End programs with M30, re-command spindle and coolant after every stop instead of trusting resume behavior, and put every stop code alone on its own line with a comment saying what the human at the machine is supposed to do. That is the complete, portable discipline for the stop family.

## Frequently asked questions

### What is the difference between M00 and M01?

M00 is an unconditional program stop: the machine halts at that line every time and waits for cycle start. M01 is an optional stop: it halts only when the control's Optional Stop toggle is switched on, and is ignored otherwise. Use M00 for mandatory actions like part flips, and M01 for useful-sometimes checks like inspecting an insert during setup, retired in production by turning the toggle off.

### Does M00 stop the spindle and coolant?

On most controls yes, both stop. What varies is the restart: some machines resume spindle and coolant automatically at cycle start, others require the operator to restart them, and a program that guesses wrong feeds a dead tool into the part. The portable habit is to re-command S, M03, and M08 explicitly on the lines after any M00 so the program never depends on control-specific resume behavior.

### Where is the optional stop button on a CNC machine?

On the operator panel, usually near the single block and block delete keys, labeled OPT STOP, M01, or Optional Stop; on many machines it is a toggle with an indicator light, on others a soft key in a settings page. Its state persists between programs, so check it during setup like any other machine state. With the toggle off, every M01 in the program is read and ignored silently.

### What is the best way to learn M codes like M00, M01, and M30?

Drill them as recall, not recognition. The stop family is small, M00, M01, M02, M30, plus the spindle and coolant codes around them, and the danger is forgetting which is which at the machine months after reading about them. A free app like G-Code Sprint quizzes these codes in short timed rounds and repeats the ones you miss, which builds the instant recall that a printed list on the wall does not.

### Is it safe to rely on M01 for a mandatory part flip?

No. An M01 disappears whenever the Optional Stop toggle is off, and an ignored stop before a part flip means the machine runs op 2 toolpaths on an unflipped part. Anything the process cannot survive skipping belongs behind M00, which stops unconditionally. Reserve M01 for stops that are genuinely optional, per-tool checks during proving, wear checks early in a run, where skipping them is a valid production choice.

## Sources

- [LinuxCNC M-code reference](https://linuxcnc.org/docs/html/gcode/m-code.html)
- [HelmanCNC Fanuc M-code list](https://www.helmancnc.com/fanuc-m-code-list/)
- [Wikipedia: Numerical control](https://en.wikipedia.org/wiki/Numerical_control)

---

Source: https://gcodepractice.com/journal/m00-vs-m01-program-stop-and-optional-stop/
Author: Lawrence Arya — https://www.linkedin.com/in/vibecoding/
