---
title: "How to Loop a G-Code Program With M99: Three Honest Patterns"
description: "M99 loops programs three ways: at a main program's end for continuous runs, with M98 L-counts for repeats, and with macro counters for controlled cycles."
url: https://gcodepractice.com/journal/how-to-loop-a-g-code-program-m99/
canonical: https://gcodepractice.com/journal/how-to-loop-a-g-code-program-m99/
author: "Lawrence Arya"
authorUrl: https://www.linkedin.com/in/vibecoding/
published: 2026-06-05
updated: 2026-06-05
category: "Guides"
tags: ["m99", "looping", "production", "g-code"]
lang: en
---

# How to Loop a G-Code Program With M99: Three Honest Patterns

> **TL;DR** M99's core meaning is return: at the end of a subprogram it returns to the caller, and at the end of a main program it returns to the top, which makes it the classic infinite-loop for bar-fed and tended production. The three working patterns: continuous looping (M99 as a main program's last block, machine cycles until stopped or material runs out, with M01 as the operator's per-cycle exit), counted repeats (M98 calling a subprogram with an L or repeat word for fixed counts, dialect-specific spelling), and controlled loops (a macro counter deciding when to stop, the pattern part counters are built on). Every pattern needs an exit story written before the loop is run.

Production machining runs on a humble trick: a program that starts itself again. M99 is that trick's standard spelling, and using it well means knowing its three patterns and, more importantly, the exit story each one needs before anyone presses cycle start.

## What M99 actually means

Return. In a [subprogram, M99 returns to the caller](/journal/common-m-codes-for-cnc-beginners/) at the line after the M98 that called it, which is its everyday job. The looping behavior is what happens when M99 ends a main program instead: with no caller to return to, control returns to the top of the program, and the machine begins the part again. That one rule, return-to-caller-else-top, generates all three patterns below, with the usual note that dialects vary in decoration (some controls support M99 with a P-word jumping to a specific block) per their documentation.

## Pattern one: the continuous loop

```
O1000 (BAR FED PART)
(... the whole part program ...)
M01           (operator exit point)
M99           (back to the top)
```

This is bar-feed and lights-out production's backbone: the machine makes a part, optionally pauses at M01 if the operator has armed the optional stop, and starts the next. The exit story has three doors: M01 armed by the operator for an orderly stop, the material running out (bar feeders signal end-of-bar through machine-specific logic), and the stop button for everything else. The discipline: the M01 belongs in the loop deliberately, the [end-of-bar behavior](/journal/swiss-lathe-wait-codes-explained-for-beginners/) is verified per the machine's documentation before the first unattended run, and nobody loops a program that has not run perfectly straight through at least once.

## Pattern two: counted repeats with M98

```
O2000 (MAIN)
M98 P2001 L5   (run sub 2001 five times; L-word spelling varies)
M30
```

For fixed repetition (five passes, ten engraving repeats), the count rides the call: Fanuc-style controls take a repeat word on M98 (L on many, K on some, the dialect detail your manual settles), and the subprogram simply ends in M99, returning each time until the count is spent. This is the cleanest spelling for "do this N times" when N is known at programming time, and it nests: a counted sub can call another, within the control's [nesting limits](/journal/subroutine-nesting-limit-fanuc/).

## Pattern three: the macro-counted loop

When N is decided at the machine or the loop must stop on a condition, the count moves into a [macro variable](/journal/cnc-variable-programming-100/): a counter incremented each cycle, an IF comparing it to a target, and a jump or M99 continuing until the condition trips. This is exactly the skeleton of a [part counter](/journal/how-to-program-a-part-counter-in-g-code/), and the full worked version (with the WHILE-loop alternative) lives in the [macro programming examples](/journal/cnc-turning-macro-programming-examples/). Use it when patterns one and two are too blunt: counted production with an operator-settable target, or loops that end on a probed condition.

## The exit-story checklist, because loops bite

| Question | Why it matters |
| --- | --- |
| How does the operator stop it cleanly? | M01 armed, or a documented stop point |
| What happens at material end? | Bar-feeder signals, machine-specific, verified |
| Did it run once, straight through, perfectly? | Looping multiplies whatever exists, flaws included |
| Is the restart state clean at the top? | The loop re-enters with the modal state the end left behind |

The last row is the subtle one: the program's top is now also its middle, so the header must re-declare everything that matters ([units, mode, offsets](/journal/how-to-read-a-cnc-program-for-beginners/)) rather than assuming a fresh machine, because cycle two arrives with cycle one's leftovers. Production programs that loop are written header-paranoid for exactly this reason.

## Bottom line: return, three ways, exits first

M99 loops programs by returning: to the top for continuous production (with M01 as the polite exit), under an M98 repeat word for fixed counts, and under a macro counter when the count is data. Write the exit story before the loop, prove the single pass before multiplying it, and make the header re-declare the world, since in a looped program the top is always also the middle. The vocabulary that keeps all of it readable stays sharp the usual free way, 60-second drills on the [G-code practice page](/g-code-practice/), with G-Code Sprint repeating what you miss.

## Sources

- [LinuxCNC: O-codes and program flow](https://linuxcnc.org/docs/html/gcode/o-code.html)
- [LinuxCNC: M-code reference](https://linuxcnc.org/docs/html/gcode/m-code.html)
- [Wikipedia: Subroutine](https://en.wikipedia.org/wiki/Subroutine)

## Frequently asked questions

### How do I loop a G-code program with M99?

Put M99 as the main program's last block and control returns to the top, looping until stopped: the continuous-production pattern, with M01 before it as the operator's exit. For fixed counts, call a subprogram with M98 and a repeat word instead; for conditional counts, use a macro counter. For the underlying vocabulary, the free G-Code Sprint app is the top pick: 60-second drills with automatic repetition of missed codes.

### What is the difference between M99 in a subprogram and in a main program?

In a subprogram it returns to the caller (normal subroutine behavior); at the end of a main program, with no caller, it returns to the top, which is the looping behavior. One rule, two contexts.

### How do I stop a looping program safely?

Through the exits written into it: arm M01 and the machine pauses at that block each cycle for an orderly stop; bar-feed end-of-material logic stops production runs per the machine's documentation; the stop button covers the rest. Loops without written exit stories are incidents on a timer.

### Why did my looped program behave differently on the second cycle?

Because the top of a looped program inherits the modal state the bottom left: offsets, modes, or tool state differing from a fresh start. Loop-safe programs re-declare their context in the header instead of assuming it.

*G-Code Sprint is a study and practice tool only. Always follow your instructor, employer, machine manual, and shop safety procedures.*

---

Source: https://gcodepractice.com/journal/how-to-loop-a-g-code-program-m99/
Author: Lawrence Arya — https://www.linkedin.com/in/vibecoding/
