CNC output

From the nest to your machine

The layered DXF ships today and works with whatever CAM you already run — VCarve, Aspire, Fusion, EnRoute, your machine's own software. The direct posts write a machine's program straight from the nest, for eight controllers.

Every direct program is simulated and read back before the app will offer it, and no WoodWright program has cut on a machine yet. Below is exactly what each file contains — check it against your own table before the first scrap cut.

design  →  parts  →  nest (true-shape, grain-locked)
                        │
          ┌─────────────┴─────────────┐
   layered DXF                   direct post
   every part of a material      one program per nested sheet
          ↓                            ↓
   your CAM                      .xxl  .tap  .nc  .ngc
   nests it, toolpaths it,       .sbp  .cix  .mpr
   writes your G-code                  ↓
          ↓                      your controller
   your router

The layered DXF

Cutlist ▸ ⬇ DXF writes one file per material, named WW-<room>-<material>.dxf, into the job's own folder — or into the folder your CAM watches, if you point Settings ▸ Folders at one.

It is ASCII DXF, R2010, in inches. It opens in anything that reads DXF, and it audits clean in an independent DXF library (ezdxf: zero errors).

The DXF is not the nest. It is every cut part of that material, each drawn in its own frame and laid out in tidy rows — 96 inches wide, 1-inch gutters — for your CAM to nest and toolpath.

A DXF of the nested sheet itself is on the bench; the nest reaches a machine through the direct posts today.

Each part sits with its origin at its bottom-left corner, X along the grain (the part's length), Y across it, top face up. Everything the router does to that part is on its own layer, and the layer name is the tool selector:

OUTLINE             the through cut — one closed polyline per part; fillets are true arcs
POCKET_0.385        a dado or groove, pocketed 0.385" deep — a closed polyline
POCKET              the same with no derived depth — set the depth in your CAM
ROUTE_0.375x0.25    a groove that is not square to an edge: the cutter CENTRELINE as
                    an open polyline — 0.375 is the bit, 0.25 the depth
BORE_0.197          a drill centre: a POINT and a CIRCLE at true diameter (5 mm here)
BORE_1.378x0.5      a 35 mm hinge cup, 0.5" deep — drill it, or run a hole toolpath on the circle
LABEL               the part name as TEXT — never a cut layer

The numbers in a layer name are decimal inches to three places. They are selectors, not measurements — the geometry underneath is exact.

In VCarve terms: OUTLINE is a profile outside the line; POCKET is a pocket to the named depth; ROUTE is a profile on the line with the named bit, to the named depth; BORE is a drill at the point, or a hole toolpath on the circle when the hole is wider than any bit you own; LABEL stays off.

Which face. Everything drawn is on the face that is up.

A part whose machining is all on the far face is drawn mirrored, with · MACHINED-FACE-DOWN in its label — the same flip the direct posts make, so the DXF shows the face the router actually cuts. A part that needs both faces refuses the whole export and says which part.

Direct posts — one toolpath, eight dialects

WoodWright has one toolpath planner. It writes SCM Xilog, because that is the machine it was decoded against: three real jobs' programs off the shop's own N100, every program re-parsed byte-identical and run through an independent dry-run simulator.

Every other post is a translation of that simulated program — move for move, bore for bore — and the translated text is then read back by its own parser and compared to the source before a machine card may offer it.

MachineFileHow it is spokenYour choices
SCM N100 · Xilog Plus.xxlThe source program itself — the dialect decoded from the shop’s own programs, re-parsed byte-identical, dry-run simulated, checked against three real jobs’ goldens.two-face
Generic router · Mach3 / Mach4.tapISO G-code: T M6 + G43 H, G91.1, G83 pecks. Avid, Laguna, most 4×8 kits.units · Z zero · tool change · two-face
Generic router · GRBL 1.1.ncM0 tool change that names the bit, pecks spelled out (no canned cycles), no G91.1, every line under 80 characters. Onefinity, Shapeoko, LongMill, OpenBuilds.units · Z zero · two-face
Generic router · LinuxCNC.ngcRS274/NGC: T M6 + G43 H, G91.1, G83 pecks.units · Z zero · tool change · two-face
Generic router · Masso G3.ncT M06 without G43 — tool geometry lives in Masso’s own table. G83 pecks.units · Z zero · tool change · two-face
ShopBot · PRSalpha / PRSstandard.sbpOpenSBP (public domain): a %(25) unit guard that halts on the wrong unit, CG arcs, C6/C7 spindle, &Tool + C9 or a PAUSE for a hand change. Inches by default.units · Z zero · tool change · two-face
Biesse Rover · bSolid / bWorks.cixBG bores, ROUT + LINE_EP paths with incremental Z (a misread lifts, never buries), arcs chorded at 0.025 mm. Z is panel-relative, so no Z-zero choice.two-face
Homag / Weeke · woodWOP.mprBohrVert bores by diameter (the control picks the drill), KP/KL contours on the tool centreline with RK=NOWRK, TI=0 so the depth lives in the points. mm only.two-face

Tick your machine in Sheets ▸ Machines — the public build starts with none ticked, so nothing posts until you say which controller reads it.

Programs save beside the job (or in the folder the machine reads), one per sheet, named WW-<room>-<material>-S01.<ext>. A SETUP.txt saves beside each one: the origin corner, the face that is up, the Z reference, and every tool with its T number.

A pinned dado bit that is not in the changer cuts with the widest capable bit that fits, and the setup sheet says so.

The ISO G-code, line by line

Mach3/4, GRBL, LinuxCNC and Masso share one emitter; the cards differ only where the controls do. This is the head of a generated program, unedited:

(WoodWright 0.7.0 - WW-Kitchen-Prefinished-S01)
(Prefinished 3/4 - sheet 1 of 3 - 2026-09-03)
(stock 2451.1 x 1231.9 x DZ 18.923 mm - X along the long axis)
(Z0 = TABLE spoilboard top; stock top at Z18.923)
(origin front-left corner of the sheet, top face up)
(sim-verified translation of the WoodWright toolpath - VERIFY ON SCRAP FIRST)
G17 G21 G90 G94 G40 G49 G54
G91.1
G0 Z33.923

The preamble. XY plane, millimetres (or G20 on an inch card — then every word is converted, feeds included), absolute positioning, feed in units per minute, cutter compensation off, tool-length offset cancelled, work offset G54.

G91.1 declares incremental arc centres on Mach and LinuxCNC; GRBL errors on that word and never sees it. Comments are in parentheses, lines end CRLF, there are no line numbers, and on GRBL no line is longer than 78 characters.

The frame and the Z reference

The origin is the front-left corner of the sheet, top face up, X along the long axis. By default Z0 is the table — the top of the spoilboard — and the stock top sits at +DZ, the thickness you mic'd and typed into the sheet.

With Z0 at the table a wrong thickness cannot bury a bit: a through cut always ends 0.127 mm into the spoilboard, wherever the stock top really was. The card offers Z0 at the top of the stock instead, for a shop that touches off the sheet.

With 18.923 mm stock the numbers in the program are:

Z33.923   safe height       stock top + 15 mm — every rapid rides here
Z19.923   hover             1 mm over the stock — the plunge starts here, at plunge feed
Z18.923   the stock top     DZ, as typed
Z-0.127   a through cut     0.127 mm into the spoilboard
Z-0.099   a through bore    the drill's own through-add

Every move the simulator cleared, move for move

G0 Z33.923                     retract to safe
G0 X187.3 Y7.938               rapid over the lead-in
G0 Z19.923                     down to the hover
G1 Z18.923 F1778               to the stock top at the tool's plunge feed
G1 X212.7 Z-0.127              the ramp the simulator cleared — 25.4 mm long
G1 X412.7 F17780               the cut, at the tool's feed (modal — said once)
G2 X417.462 Y12.7 I0 J4.762    a filleted corner: incremental I/J from the current point
G1 Y312.7

Every path is the tool centreline — the offsets are already in the geometry, which is why the program runs G40 and a control with cutter compensation on would cut it twice.

Feeds are the tool library's (Sheets ▸ Tooling), spindle speed rides S… M3 at each change. Onion-skin tabs every 24 inches are on by default (the G-code modal has the box); the ramps and tab lifts are explicit moves, never a cycle.

Tool changes

Mach / LinuxCNC                 Masso
M5                              M5
G0 Z33.923                      G0 Z33.923
T1 M6                           T1 M6
G43 H1                          S24000 M3
S24000 M3

GRBL, or "change by hand" on any card
M5
G0 Z33.923
T1
(CHANGE TO T1 3/8 Compression d9.525 then cycle start)
M0
S24000 M3

T numbers are the app's own tool-library numbers, and the setup sheet lists each one with its name, diameter, rpm and feed, so the changer or the hand can be checked against the paper. Masso keeps tool geometry in its own table and is correct without G43 — that is deliberate, not an omission.

Bores on a machine with no drilling head

A router has no drill bank, so the post decides. A bit of the hole's diameter that is marked for drilling pecksG83 with a 4 mm peck, or the pecks spelled out as G1/G0 pairs on GRBL.

A hole wider than any drill you own is helix-bored with the largest suitable smaller bit: full-circle G2 arcs stepping down 1.5 mm a turn, one flat turn at the bottom. A hole nothing in your library can make refuses the sheet and names the bit to add.

(1 x d5 pecked with 5mm Drill)
G83 X1100 Y950 Z-0.099 R19.923 Q4 F1200
G80

(1 x d35 helix-bored with 3/8 Compression)
G0 X1012.737 Y900
G0 Z19.923
G1 Z18.923 F1778
G2 X1012.737 Y900 Z17.423 I-12.738 J0 F17780
G2 X1012.737 Y900 Z15.923 I-12.738 J0
…
G2 X1012.737 Y900 Z6.223 I-12.738 J0
G2 X1012.737 Y900 I-12.738 J0

What the program does not do

  • No dust-collector or coolant words (M7/M8) — put those in your control's tool-change macro if you want them.
  • No probing, no tool-length measuring, no setting of the work offset — it assumes G54 is your sheet corner.
  • No cutter compensation — every path is the centreline, offsets already applied.
  • No second sheet in one file — one program per sheet, one setup sheet beside it.
  • The footer is M5 · G0 Z-safe · M30. Nothing parks, nothing homes.

ShopBot, Biesse, Homag

The same translation, spoken three other ways. Each was built from the public format description only — no vendor post file was copied — and where the public text leaves a token ambiguous, the conservative reading was taken and the program's own header says which.

ShopBot (.sbp) never sets the control's units — a wrong calibration value would miscalibrate the machine — it guards them and halts:

'stock 96.5 x 48.5 x DZ 0.745 in - X along the long axis
'Z0 = TABLE (spoilboard top); stock top at Z0.745
'units INCHES; speeds in in/sec; the file halts if the control is set to the other unit
IF %(25)=1 THEN GOTO UNIT_ERROR
SA
JZ,1.3356

Cuts are M2/M3/MZ, jogs J2/J3/JZ, arcs CG with the diameter written as well as the centre so either reading of the centre words gives the same circle, spindle TR … C6 … C7, and a hole wider than the bit is stepped — plunge a pitch, one flat circle, again — rather than helixed.

Biesse (.cix) carries the stock in MAINDATA (LPX, LPY, LPZ), Z is the top of the panel, a bore the library can drill is a BG macro, a path is ROUT + LINE_EP elements with incremental Z — the reading under which a misread lifts the bit rather than burying it — and arcs are chorded at 0.025 mm sag because the arc direction word is not corroborated.

Homag / Weeke (.mpr) is woodWOP's own file: the [H header with DX/DY/DZ, a BohrVert macro per bore with the diameter so the control picks its own drill — no peck, no helix, no library lookup — and KP/KL contours on the tool centreline with RK="NOWRK" so woodWOP does not offset a second time. Feeds and rpm are written in each macro's comment and ride your tool database.

Before the first cut

The first time a machine saves programs on a device, the app puts this in front of the hand that saves them, and the box has to be ticked. These are its words:

  • Every program here was re-parsed and dry-run simulated clean — a simulation is not a router.
  • Run it on SCRAP (or MDF) first, at reduced feed, with a hand on the stop.
  • First pass with the bit raised clear of the stock — watch where it goes before it cuts.
  • Check the origin corner, the face that is up, and the Z reference on the SETUP sheet against your table.
  • Measure the first part against the cut list before cutting the sheet of prefinished.
  • What the machine does is on the hand that presses go — WoodWright cannot see your table.

Your machine isn't here

Sheets ▸ Machines ▸ tell us about your machine hands us the maker, model, controller and bed with the details prefilled. A sample program your CAM writes today — any .nc, .sbp, .mpr, .cix — helps most, because a post is built by reading what the machine already eats.

And if you have run a WoodWright program on iron: send the measured first part through support and that machine's card gets a proven-on date. The bench order follows real shops.