If you have recently purchased a CNC machine, you’ve probably spent hours watching it carve intricate designs using CAM (Computer-Aided Manufacturing) software. It feels like magic. But behind the scenes, that “magic” is actually a highly logical, plain-text programming language called G-Code.
While CAM software is incredible for complex 3D carvings, relying on it entirely is like using a GPS without ever learning how to read a map. If something goes wrong or if you just need to make a quick, simple cut knowing how to write G-Code by hand is an invaluable superpower.
In this step-by-step guide, we are going to strip away the complexity. We are going to write a G-Code program completely from scratch to machine a simple 2×2 inch square. By the end, you will understand the anatomy of a program and be ready to hit “Start” on your machine.
Understanding the Basics: G-Code vs. M-Code
G-Code is the language that tells your CNC machine where to go and how to move. It stands for “Geometric Code.” Within G-Code, there are also “M-Codes,” which stand for “Miscellaneous Codes.” M-Codes tell the machine to perform non-movement actions, like turning the spindle on or off.
For our simple square program, we only need to know a handful of these commands. Think of these as your vocabulary words for today:
Movement Codes:
- G0 (Rapid Move): Moves the machine as fast as possible to a specific coordinate. The spindle remains at its current height. Used for positioning, not cutting.
- G1 (Linear Feed Move): Moves the machine in a straight line at a controlled speed (Feedrate). This is the code used for actual cutting.
Positioning Codes:
- G20 (Inch Mode): Tells the machine all coordinates are in inches. (Note: If you prefer metric, you would use G21).
- G90 (Absolute Positioning): Tells the machine that all coordinates are measured from a fixed zero point (the origin). Every X, Y, or Z value is an exact location on the workbed.
Machine Control (M-Codes):
- M3: Spindle On (Clockwise).
- M5: Spindle Off.
- M8: Coolant On (Flood or Mist).
- M9: Coolant Off.
- M30: End of Program and Reset (Rewinds the code to the beginning for the next run).
The Anatomy of a G-Code Program
Every well-written G-Code program, no matter if it’s 10 lines or 10,000 lines, follows a classic three-act structure:
- The Setup (Safety & Initialization): Telling the machine what units to use, turning on the spindle, and positioning the tool safely above the material.
- The Body (Machining): The actual toolpath where the cutting happens.
- The Finale (Retract & Reset): Pulling the tool away, turning off the spindle and coolant, and ending the program.
Step 1: Define Your Part and Toolpath
Before typing a single letter, you must visualize the cut.
- The Part: A 2″ x 2″ square.
- The Tool: Let’s assume we are using a 1/4″ (0.25″) flat end mill.
- The Depth: We want to cut 0.1″ deep in a single pass (for simplicity).
- The Origin (Zero Point): We will set our X0, Y0 at the bottom-left corner of the square, and Z0 at the top surface of the material.
Crucial Concept – Tool Diameter Compensation:
Because our end mill is 0.25″ wide, its center cannot travel exactly along the 2″ lines, or the part will end up too small. The center of the tool must be offset by half the tool’s diameter (0.125″) outside the part.
Therefore, our toolpath coordinates will actually be:
- Start: X-0.125, Y-0.125
- Top Right: X2.125, Y-0.125
- Top Left: X2.125, Y2.125
- Bottom Left: X-0.125, Y2.125
- Back to Start: X-0.125, Y-0.125
Step 2: Writing the Setup Block
Open a plain text editor (Notepad, VS Code, or the built-in editor in software like Candle or GRBLControl). Do not use Microsoft Word, as it will add invisible formatting that breaks the code.
Let’s write the setup:
%
G20 G90
M3 S12000
M8
G0 X-0.125 Y-0.125
G0 Z0.5
What does this mean?
%: A standard program start character recognized by most machines.G20 G90: We are working in Inches (G20) and Absolute Positioning (G90). We can put these on the same line to save space.M3 S12000: Turn the spindle clockwise (M3) at a speed of 12,000 RPM (S12000). Adjust this to your specific material and tool.M8: Turn on the coolant to keep the tool cool and clear chips.G0 X-0.125 Y-0.125: Rapid move the tool to our calculated start position just off the bottom-left corner.G0 Z0.5: Rapid move the Z-axis up to 0.5 inches above the material. This ensures we don’t crash into the part while moving into position.
Step 3: Machining the Part (The Body)
Now we are positioned directly above our start point. It’s time to cut.
G1 Z-0.1 F10
G1 X2.125 F30
G1 Y2.125
G1 X-0.125
G1 Y-0.125
What does this mean?
G1 Z-0.1 F10: We switch to a linear feed move (G1), plunge the tool down to Z-0.1 (0.1 inches deep into the material), and set a Feedrate (F) of 10 inches per minute (IPM). Plunging straight down is hard on the tool, so we use a slow feedrate.G1 X2.125 F30: Move right to X2.125. Notice we changed the feedrate to 30 IPM. Once the feedrate is set, it stays active for all subsequent G1 moves until you change it again. 30 IPM is a reasonable conservative cutting speed for wood or soft aluminum.G1 Y2.125: Move up the right side of the square.G1 X-0.125: Move left across the top.G1 Y-0.125: Move down the left side, completing the square.
Step 4: The Finale (Retract and Reset)
We have completed our cut, but we cannot just turn the machine off while the tool is buried in the material. We need a safe exit.
G0 Z0.5
M5
M9
G0 X0 Y0
M30
%
What does this mean?
G0 Z0.5: Rapid the tool straight up to 0.5 inches above the material. We use G0 (Rapid) here because we are no longer cutting; we just want to get out of the way quickly.M5: Turn the spindle off.M9: Turn the coolant off.G0 X0 Y0: Rapid move the tool back to the absolute zero corner of the machine. This gets the tool out of your workspace so you can remove the part.M30: End of program. The machine will stop and reset to the beginning of the code.%: The standard program end character.
Step 5: Putting It All Together
Let’s look at the complete, finalized program. In G-Code, any text following a semicolon (;) is a “comment.” The machine ignores comments, but they are incredibly helpful for humans reading the code later. Let’s add comments to our final masterpiece.
%
(SIMPLE 2X2 INCH SQUARE - WRITTEN BY HAND)
(UNITS: INCHES, TOOL: 0.25" END MILL)
(--- SETUP BLOCK ---)
G20 G90 (SET INCHES AND ABSOLUTE POSITIONING)
M3 S12000 (TURN SPINDLE ON CLOCKWISE AT 12K RPM)
M8 (TURN COOLANT ON)
G0 X-0.125 Y-0.125 (RAPID MOVE TO START POSITION JUST OUTSIDE PART)
G0 Z0.5 (RAPID MOVE TO SAFE HEIGHT 0.5" ABOVE MATERIAL)
(--- MACHINING BLOCK ---)
G1 Z-0.1 F10 (PLUNGE INTO MATERIAL 0.1" DEEP AT 10 IPM)
G1 X2.125 F30 (CUT BOTTOM EDGE RIGHT AT 30 IPM)
G1 Y2.125 (CUT RIGHT EDGE UP)
G1 X-0.125 (CUT TOP EDGE LEFT)
G1 Y-0.125 (CUT LEFT EDGE DOWN TO CLOSE THE SQUARE)
(--- FINALE BLOCK ---)
G0 Z0.5 (RAPID Z UP TO SAFE HEIGHT)
M5 (TURN SPINDLE OFF)
M9 (TURN COOLANT OFF)
G0 X0 Y0 (RAPID MOVE BACK TO MACHINE ZERO)
M30 (END PROGRAM AND RESET)
%
Save this file as square.nc or square.gcode.
Step 6: Testing Your Code (Crucial!)
Never send untested code to your CNC machine with a bit installed and material on the bed. Even experienced programmers make typos. Here is the safest way to test your first program:
- Use a Simulator: Before you even turn on your machine, copy and paste your code into a free online G-Code simulator like NCViewer. This will draw the toolpath on a 3D grid and immediately alert you if there are syntax errors or if the tool crashes into an invisible boundary.
- Air Cutting: Once you load the file into your machine control software (like Candle, UGCS, or Mach3), remove the material from the bed. Keep the cutting tool installed.
- Watch the Z-Axis: Turn on the machine and run the program. Watch carefully. Did the tool plunge down to exactly -0.1 before moving in the X and Y axes? Or did it accidentally rapid (G0) down into the bed? Air cutting will save you from a broken bit or a scorched table.
- Measure: After the air cut, bring the tool to your start position and double-check the coordinates against a tape measure to ensure your square will actually be 2×2 inches.
Common Beginner Pitfalls to Avoid
As you venture deeper into writing G-Code, keep these common beginner mistakes in mind:
- Forgetting the Decimal Point: In G-Code,
G0 X1means exactly the same thing asG0 X1.0(one inch). However,G0 X10means ten inches. If you mean “ten thousandths of an inch” (0.010″), you must typeX0.010. If you typeX.010orX010, some machines will interpret it as ten inches and crash. Always use a leading zero for numbers less than 1 (e.g.,0.1, not.1). - No Safe Z Height: Always include a
G0 Z0.5(or higher) before making large X/Y movements. If you forget this, the tool will drag across your material at cutting depth, ruining the part and likely breaking the tool. - Confusing G0 and G1: Never use
G0when the tool is touching the material.G0ignores feedrates and will slam the bit into the material at the machine’s maximum speed.
Conclusion
Congratulations! You’ve just written your first G-Code program. While a 2×2 square might not seem like much, the framework you just learned is the exact same framework used to machine aerospace components. The only difference is that complex parts use arcs (G2/G3), tool changes, and sub-programs nested within this exact same three-act structure.
Now that you know how to speak to your machine, you’ll find that troubleshooting CAM-generated code becomes much easier. You can open a massive 10,000-line file, find the specific line causing an error, and actually understand what the machine is trying to do.




