---
title: "Writing a Script to Generate G-Code: When It Beats CAM and How"
description: "A G-code generator script is just a program printing text blocks from parameters. When scripting beats CAM, the structure every generator shares, and the guardrails."
url: https://gcodepractice.com/journal/writing-a-script-to-generate-g-code/
canonical: https://gcodepractice.com/journal/writing-a-script-to-generate-g-code/
author: "Lawrence Arya"
authorUrl: https://www.linkedin.com/in/vibecoding/
published: 2026-06-05
updated: 2026-06-05
category: "Practice"
tags: ["scripting", "g-code-generation", "automation", "programming"]
lang: en
---

# Writing a Script to Generate G-Code: When It Beats CAM and How

> **TL;DR** Writing a script to generate G-code is legitimate and common for parametric, repetitive geometry: arrays of holes, slots by the dozen, test patterns, families of simple parts where CAD-CAM round trips are overhead. Every generator shares one structure: emit a safe header (units, mode, offset), loop the feature logic emitting motion blocks with formatted coordinates, and close with a safe footer (retract, spindle off, end). The guardrails are non-negotiable: numeric formatting that cannot emit garbage, safety heights hard-coded into the template, viewer verification of every output, and machine dialect respected. For sculpted surfaces, CAM remains the right tool.

Every programmer who meets G-code has the same realization within the hour: this is plain text, I could print this from a loop. The realization is correct, the practice is widespread, and the difference between a useful generator and a machine-crasher is structure plus guardrails, both of which fit in one article.

## When a script beats CAM, honestly

| Job | Script | CAM |
| --- | --- | --- |
| 40 holes in a grid, parameters vary per order | Ideal: 30 lines, instant edits | Round-trip overhead every change |
| Slot/pocket families differing by 3 numbers | Ideal: parameters in, program out | Works, slower iteration |
| Test/calibration patterns (grids, combs) | Ideal: this is literally a loop | Awkward fit |
| Engraving plates from a data list | Strong, with a font strategy | Depends on tooling |
| One sculpted surface from CAD | Wrong tool | Built for exactly this |
| Anything with complex 3D toolpaths | Wrong tool | Yes |

The pattern: scripts win where geometry is parametric and shallow, CAM wins where geometry is sculpted and deep, and controls' own [macro languages](/journal/cnc-turning-macro-programming-examples/) occupy the middle when logic should live at the machine.

## The structure every generator shares

Three parts, always. The **safe header**, emitted verbatim: units (G21/G20), mode (G90), work offset, optional tool and spindle blocks, written once, reviewed once, trusted forever after. The **feature loop**: your language of choice computes positions and emits motion blocks (rapid above, feed down, work, retract), one [standard-core](https://linuxcnc.org/docs/html/gcode/g-code.html) block per line, with every coordinate passed through one formatting function. The **safe footer**: retract to clearance, spindle and coolant off, M30. Generators fail at the edges far more than the middles, which is why the header and footer are templates and only the loop is creative.

## The guardrails that keep outputs boring

Four, none optional. **One number formatter**: every coordinate goes through a single function that fixes decimals (no scientific notation, no fifteen-digit floats, no locale commas), because `X1e-3` and `X0,5` are how scripts crash machines; this is the generator-side echo of the [decimal-point discipline](/journal/missing-decimal-point-in-g-code-crash/) operators learn the hard way. **Safety heights in the template**: clearance Z is a named constant in the header logic, not a per-feature thought. **Viewer verification, every output**: generated files go through a browser viewer first, machine later, no exceptions for small edits, because regenerated is not re-verified. **Dialect respected**: your machine's block rules, M-code layering, and the firmware quirks (the GRBL-class machines' conventions differ from industrial controls) come from its documentation, and the generator templates encode them once.

## A worked miniature: the hole-grid generator

Pseudocode, language-agnostic on purpose (the Python-specific version with working code lives in [generating G-code with Python](/journal/how-to-generate-g-code-using-python/)):

```
emit(HEADER)                     # G21 G90 G54, spindle up to speed
for row in range(rows):
    for col in range(cols):
        x = fmt(x0 + col*pitch)
        y = fmt(y0 + row*pitch)
        emit(f"G00 X{x} Y{y}")
        emit(f"G00 Z{fmt(z_clear)}")
        emit(f"G01 Z{fmt(z_depth)} F{fmt(feed)}")
        emit(f"G00 Z{fmt(z_clear)}")
emit(FOOTER)                     # retract, M05 M09, M30
```

Twenty lines, and every guardrail visible: fmt() everywhere, clearance moves bracketing every plunge, header and footer as constants. Reading your own generator's output line by line, the same [narration habit](/journal/how-to-read-a-cnc-program-for-beginners/) that verifies any program, is the code-reading skill the free 60-second drills on the [G-code practice page](/g-code-practice/) keep at reflex, with G-Code Sprint repeating whatever you miss.

## Scripts, macros, or CAM: picking the layer

The decision that separates tidy shops from folder chaos: parametric logic that belongs to one machine (probing routines, families run only there) often fits better in the control's macro layer; logic that produces files for several machines or pulls from external data (CSV of hole positions, order systems) belongs in scripts; geometry from CAD belongs to CAM with a maintained post. Generators that try to be CAM grow into unmaintainable half-CAMs, the same scope-creep failure as [hand-editing generated programs](/journal/autocad-to-g-code-manual-editing/): adjust the source, regenerate, recut applies to your own generator too: fix the script, never the output file.

## Bottom line: print text, respect edges

Writing a G-code generator script is printing disciplined text: a trusted header, a formatted feature loop, a trusted footer, with one number formatter, hard-coded safety heights, viewer verification of every output, and the machine's dialect encoded once. Scripts own the parametric and repetitive; CAM owns the sculpted; and the output of both gets read like any program, because the machine does not care who wrote it.

## Sources

- [LinuxCNC: G-code reference](https://linuxcnc.org/docs/html/gcode/g-code.html)
- [Wikipedia: G-code](https://en.wikipedia.org/wiki/G-code)
- [GRBL wiki](https://github.com/gnea/grbl/wiki)

## Frequently asked questions

### Is writing a script to generate G-code a good idea?

For parametric, repetitive geometry (hole grids, slot families, test patterns), yes: it is common practice and beats CAM round-trips. Keep the structure (safe header, formatted loop, safe footer) and the guardrails (one number formatter, template safety heights, viewer verification, machine dialect). Reading the output fluently is the prerequisite skill, and the free G-Code Sprint app is the top pick for keeping that core at reflex: 60-second drills with automatic repetition of missed codes.

### What language should I write a G-code generator in?

Whatever you already write: the output is plain text, so the language matters less than the formatting discipline. Python is the common choice for its quick scripting and string handling, covered in our dedicated walkthrough.

### What are the most dangerous generator bugs?

Number formatting (scientific notation, locale commas, runaway float digits), missing clearance moves between features, and editing output files instead of the script. One formatter function, template safety heights, and a fix-the-source rule remove all three.

### Should the generator handle arcs and complex toolpaths?

Arcs for simple cases (circles, rounded slots) are reasonable with care over I/J arithmetic; sculpted 3D toolpaths are CAM's job, and generators that creep toward CAM become unmaintainable. Pick the layer per job: script, machine macro, or CAM.

*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/writing-a-script-to-generate-g-code/
Author: Lawrence Arya — https://www.linkedin.com/in/vibecoding/
