G-Code & M-Code Fundamentals
Every CNC machine—mill, lathe, router, or machining center—runs on the same basic language: lines of G-codes and M-codes that tell it where to move, how fast, and when to turn things on and off. This page is the on-ramp. If you can read a tape measure and you have watched a machine cut, this is everything you need to start reading a program and understanding what each line does. No prior code experience assumed.
What a G-Code Program Actually Is
A CNC program is a plain-text list of instructions the control reads top to bottom, one line at a time. The vocabulary is small and rigid, which is good news—there is a fixed set of building blocks and once you know them, every program looks familiar.
The two families of codes that do the heavy lifting have formal names worth knowing:
- G-codes are the preparatory commands. They prepare (preset) the control into a mode of operation—rapid vs. feed motion, inch vs. metric, absolute vs. incremental. Think of them as the machine's settings and moves.
- M-codes are the miscellaneous functions. They switch hardware and manage program flow—spindle on/off, coolant on/off, tool change, program end.
Everything else in a program is built from a handful of pieces:
| Piece | What it is | Example |
|---|---|---|
| Word | A single instruction: one letter (the address) followed by a number | G01, X2.5, F10. |
| Block | One line of the program—one or more words the control executes together | G01 X2.5 Y1.0 F10. |
| Sequence number | An optional N word that labels a block so you can find or search to it | N50 |
| Program number | The O word that names the program in control memory (Fanuc) | O0001 |
| Comment | Human notes in parentheses—ignored by the machine | (DRILL 1/4 HOLE) |
| Block skip | A leading / makes the control skip that block only when the Block Skip switch is on | /M08 |
| Program marker | The % character marks the start and end of the program file | % |
A word is always a letter plus a number. The letter (the address) says what kind of information follows; the number is the value. X2.5 means "X axis, 2.5 units." F10. means "feedrate, 10." Here are the address letters a beginner meets first:
| Address | Meaning |
|---|---|
O | Program number |
N | Block (sequence) number |
G | Preparatory command (a mode or a move) |
M | Miscellaneous function (hardware / flow) |
X Y Z | Axis positions |
F | Feedrate (cutting speed of the tool through the material) |
S | Spindle speed (RPM) |
T | Tool number |
H / D | Offset register numbers (length / diameter) |
R | Radius or a retract/reference height in a cycle |
P / L | Dwell time, subprogram number, or repeat count (context-dependent) |
Anatomy of a Block
Read this single block left to right and you have read a CNC program in miniature:
N50 G01 X2.5 Y1.0 Z-0.25 F10. (CUT TO CORNER)
| | | | | | |
| | | | | | +-- comment, ignored by the machine
| | | | | +------- F10. feedrate: 10 units per minute
| | | | +------------- Z-0.25 depth
| | | +------------------- Y1.0 Y position
| | +------------------------ X2.5 X position
| +----------------------------- G01 move in a straight line at feed
+--------------------------------- N50 this block's sequence number
Order of words inside a block does not usually matter to the control, but shops write them in a consistent order (G, then coordinates, then F) so programs are easy to read. What does matter is which codes are present—and, as the next section explains, which codes are still active from earlier blocks.
The Big Idea: Modal vs Non-Modal
This is the single most important concept for a beginner, and the one that causes the most crashes when it is misunderstood.
A modal code stays in effect once you program it—it stays active block after block until you change it. A non-modal (or "one-shot") code takes effect for its own block only, then evaporates. Most G-codes are modal; most M-codes are one-shots.
Because motion codes are modal, you do not repeat them on every line. Look:
G01 X1.0 Y1.0 F10. (G01 selects straight-line feed)
X2.0 (STILL G01 - no need to repeat it)
X3.0 Y2.0 (STILL G01, STILL F10.)
G00 X0 Y0 (now G00 rapid REPLACES G01)
The flip side is the trap: a mode you set 30 lines ago is still on unless something canceled it. Leave the control in G91 incremental when the next block assumes absolute, and the tool goes somewhere you did not intend. This "leftover mode" problem is exactly why programs open with a safe start line (shown later) that forces the important modes to known values before any cutting begins.
Modal Groups: One Winner Per Category
Modal codes are organized into modal groups. A group is a set of codes that do the same kind of job—and only one code from a group can be active at a time. Program a new code from a group and it automatically replaces whatever was active in that group. You cannot be in rapid G00 and feed G01 at once; they are in the same group, so the later one wins.
Each modal group holds exactly one active code (highlighted); programming another member of the same group replaces it.
That rule is why you can safely stack several G-codes in one block—as long as they come from different groups they do not fight. G17 G20 G90 is fine (three different groups). G00 G01 in one block is a conflict; on a Fanuc the later code simply wins, with no error. These are the groups you will actually use:
| Group | Controls | Members | Default at power-on* |
|---|---|---|---|
| Motion (01) | How the tool moves | G00 G01 G02 G03 | G00 or G01 (set by machine) |
| Plane (02) | Which plane arcs & cycles work in | G17 G18 G19 | G17 (XY) |
| Distance (03) | Absolute vs incremental coords | G90 G91 | G90 (absolute) |
| Feed mode (05) | Feed per minute vs per rev | G94 G95 | G94 (per minute) |
| Units (06) | Inch vs metric input | G20 G21 | Last set (survives power-off) |
| Cutter comp (07) | Tool radius compensation | G40 G41 G42 | G40 (off) |
| Tool length (08) | Tool length offset | G43 G44 G49 | G49 (off) |
| Canned cycle (09) | Drilling/boring/tapping cycles | G73 G76 G81–G89 G80 | G80 (cancel) |
| Work offset (14) | Which part-zero is active | G54 G55 G56 G57 G58 G59 | G54 |
*The group numbers above are Fanuc's internal labels and the defaults are typical—a machine builder can change them with a parameter, so confirm the power-on state for each machine you run. The concept (one active code per group, new replaces old) is the same on every ISO-style control. Note that the "one-shot" codes—dwell G04, the home-return codes G28/G30, machine-coordinate G53—live in a non-modal group (00) and do not stick around.
The Common G-Codes
You do not need to memorize the whole book. This grouped list is the set a beginner meets first—learn these and you can read the majority of milling programs. (Canned cycles like G81/G83 get their own treatment; see Canned Cycles.)
| Code | What it does |
|---|---|
| Motion | |
G00 | Rapid—move to a position as fast as possible (positioning, not cutting) |
G01 | Linear feed—move in a straight line at the programmed feedrate (cutting) |
G02 | Circular feed, clockwise arc |
G03 | Circular feed, counterclockwise arc |
| Dwell (non-modal) | |
G04 | Dwell—pause for a set time (e.g. G04 P1000 = 1 second). Its own block. |
| Plane / Units / Distance | |
G17 / G18 / G19 | Select the working plane: XY / ZX / YZ |
G20 / G21 | Inch input / metric input |
G90 / G91 | Absolute / incremental coordinates |
G94 / G95 | Feed per minute / feed per revolution |
| Coordinates & offsets | |
G28 | Return to machine home (reference point), usually via an intermediate point |
G53 | Move in machine coordinates for this block only (ignores work offset) |
G54–G59 | Select work coordinate system 1–6 (your part zero) |
G43 / G49 | Apply tool length offset (with an H number) / cancel it |
G40 / G41 / G42 | Cutter radius comp off / left / right (with a D number) |
Work offsets (G54–G59) and tool length offset (G43) are the bridge between your program's numbers and where the part physically sits in the machine—that whole subject is covered in Coordinate Systems & Work Offsets.
The Common M-Codes
One caution before the table: M-codes are far less standardized than G-codes. The core flow and spindle codes below are near-universal, but many M-codes are assigned by the machine builder and mean nothing on another machine. Always keep the M-code list from your machine's manual handy.
| Code | What it does |
|---|---|
| Program flow | |
M00 | Mandatory program stop—machine halts until the operator presses Cycle Start |
M01 | Optional stop—stops only if the Optional Stop switch is on |
M02 | End of program (older form, no rewind) |
M30 | End of program with reset and rewind back to the top (the usual ending) |
| Spindle | |
M03 | Spindle on, clockwise (normal) |
M04 | Spindle on, counterclockwise (reverse) |
M05 | Spindle stop |
M19 | Orient the spindle to a fixed angle (needed for tool changes and back-boring) |
| Tool & coolant | |
M06 | Tool change—swap in the tool selected by the T word |
M08 | Flood coolant on |
M09 | Coolant off |
| Subprograms | |
M98 | Call a subprogram (M98 P____ = call that program number) |
M99 | End of subprogram / return to the caller (also ends a macro) |
M198 | Call a subprogram stored on an external device (drip-feed / DNC) |
Subprograms (M98/M99) let you write a hole pattern or toolpath once and reuse it—the first real step toward automation and, eventually, macros.
Feeds, Speeds, Units, and Direction
Two words control how aggressively the machine cuts:
- S = spindle speed in RPM.
S1500 M03spins the tool at 1500 RPM clockwise. S sets the number; M03/M04/M05 actually start or stop it. - F = feedrate, how fast the tool advances through the material. Under
G94that is distance per minute (inch/min or mm/min); underG95it is distance per spindle revolution.
Feedrate only applies to feed moves (G01/G02/G03). Rapid moves (G00) ignore F and run at the machine's maximum traverse rate—which is exactly why you never rapid into the part.
Inch vs metric is set by G20 (inch) / G21 (metric). This is not cosmetic: it changes what every coordinate means. X2.5 is two-and-a-half inches under G20 and two-and-a-half millimeters under G21. Set it once at the top and never assume—it is one of the modes that survives a power cycle.
Absolute (G90) vs incremental (G91) changes what coordinates count from. In absolute, every X/Y/Z is a position measured from part zero. In incremental, every X/Y/Z is a distance to move from where the tool is right now. The same two moves, written both ways:
(ABSOLUTE - coordinates are positions from part zero)
G90 G00 X1.0 Y1.0 (go to the point 1.0, 1.0)
X3.0 Y1.0 (go to the point 3.0, 1.0)
(INCREMENTAL - coordinates are distances from here)
G91 G00 X1.0 Y1.0 (move +1.0 in X and +1.0 in Y)
X2.0 Y0 (move +2.0 in X, 0 in Y -> lands at the same spot)
Both reach the same place. Beginners should default to absolute (G90)—a single wrong number in incremental compounds into every move after it.
Your First Complete Program
Here is a whole, runnable program that drills one hole in the top of a plate, with part zero at the lower-left corner and the top face. It is deliberately small so you can see the shape of a complete program—setup, the work, and a clean shutdown—end to end. Read it once, then read the line-by-line notes.
%
O0001 (DRILL ONE HOLE)
N10 G20 G17 G40 G49 G80 G90 (SAFE START LINE)
N20 G54 (SELECT PART ZERO)
N30 T1 M06 (PUT TOOL 1 IN THE SPINDLE)
N40 S1500 M03 (SPINDLE ON CW, 1500 RPM)
N50 G00 X1.0 Y1.0 (RAPID ABOVE THE HOLE)
N60 G43 H01 Z0.5 M08 (TOOL LENGTH ON, RAPID TO 0.5 ABOVE, COOLANT ON)
N70 G01 Z-0.25 F5.0 (FEED DOWN TO -0.25 DEEP AT 5 IN/MIN)
N80 G00 Z0.5 M09 (RAPID OUT OF THE HOLE, COOLANT OFF)
N90 G91 G28 Z0 (RETURN Z TO MACHINE HOME)
N100 M05 (SPINDLE STOP)
N110 M30 (PROGRAM END AND REWIND)
%
| Block | Line by line |
|---|---|
% / O0001 | File-start marker, then the program number and a comment naming it. |
N10 | The safe start line. It forces the dangerous modal groups to known values before anything moves: inch (G20), XY plane (G17), cutter comp off (G40), length comp off (G49), canned cycle off (G80), absolute (G90). This is your insurance against leftover modes from the last program. |
N20 | Select work coordinate system G54—the part zero you touched off on the machine. |
N30 | Load tool 1. T1 selects it, M06 performs the change. |
N40 | Set 1500 RPM and start the spindle clockwise. Note S and M03 together. |
N50 | Rapid (G00) to a safe point directly over the hole. Z has not moved down yet. |
N60 | Activate tool length offset (G43 with height register H01), rapid down to 0.5 above the surface, and turn coolant on (M08). |
N70 | The actual cut: feed (G01) straight down to 0.25 deep at 5 in/min. This is the only F in the program—it stays modal but nothing else uses it. |
N80 | Rapid back up clear of the part and shut coolant off. |
N90 | Send Z to machine home. G91 makes the G28 move incremental so it is safe regardless of position; G28 Z0 means "go home in Z through the current point." |
N100–N110 | Stop the spindle, then end the program and rewind (M30). |
That is the skeleton every milling program shares: safe start → pick offset and tool → spindle on → get above the work → length offset + approach + cut → retract → go home → end. Real programs add more tools and more cuts, but the frame stays the same.
Where Dialects Differ
Everything above is Fanuc / ISO style, the most common family and the baseline the rest of this wiki assumes. Most controls—Haas, Mazak's EIA/ISO mode, Mitsubishi, and Fanuc itself—speak very close to this dialect, with small differences in optional codes. But two big families are genuinely different animals:
- Siemens SINUMERIK uses named programs instead of O-numbers, calls tools by name, and runs canned cycles as function calls (
CYCLE81(...)) rather than G-codes. It can also run a Fanuc-style ISO mode. See Siemens ISO Mode and Sinumerik Programming Basics. - Heidenhain Klartext is a conversational, plain-language format built around
L(line) andCC/C(arc) blocks and Q-parameters—it looks nothing like G-code at a glance, though Heidenhain controls also accept ISO. See the Heidenhain Series Guide.
Even where the syntax diverges, the concepts on this page—modal state, work offsets, feeds and speeds, cutter comp—carry straight over. Learn them once here and every control gets easier.
Next steps once this clicks: Coordinate Systems & Work Offsets (where part zero comes from), Canned Cycles (drilling and boring in one line), and Intro to CNC Macros (when you want variables and logic instead of fixed numbers).
References
- Peter Smid, Fanuc CNC Custom Macros (Ch. 1–3: Review of G-codes, M-codes and Subprograms), Industrial Press, 2005.
- Fanuc, Operator’s Manual (Preparatory Function and Miscellaneous Function chapters), FANUC Corporation.
Have a question or want to contribute?
Contact us with corrections, additions, or topics you'd like covered.
Get in Touch