Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

NullCad

NullCad is a 2D CAD application purpose-built for cadastral surveying, built with Rust, egui, and a custom wgpu renderer. It is designed to provide a modern, efficient, and precise alternative to the big name CAD programs.

Most CAD software is designed for engineers with surveying being an afterthought or functionality added through seperate plugins that are never quite able to overcome the inherint limitations of the native DXF/DWG file format.

Nullcad is designed from the ground up for the way Land Surveyors actually work.

This book covers how to use NullCad day to day — navigation, drawing and modify tools, snapping, layers, the survey workflow, drafting and PDF output, import/export formats, and the plugin/automation systems.

Where to start

Highlights

  • Phase-based survey workflow with independent camera state and status tracking per phase.
  • Full snap tracking for easy and efficient drawing and editing of survey geometry.
  • Vector PDF export of drafting sheets, with viewports, sheet templates, and title-block substitution.
  • Pure-Rust import/export for Shapefile, GeoJSON, DXF, and CSV, with optional GDAL support for KML, GeoPackage, MapInfo TAB, and FileGDB.
  • Lua plugin system and an in-process MCP server for scripting and AI agent integration.
  • ZIP-based .nullcad archive format with full operation history, undo audit trail, and embedded resources.

License

Copyright 2026. All rights reserved.

Installation

The latest release is available from Nullcad.io

PlatformFormats
LinuxAppImage
Windows.exe installer

Download the installer for your platform from the latest release and run it.

On windows, you will likely see a smart screen warning. This is normal for new software and can be bypassed by clicking “More info” and then “Run anyway”. The binary has not been signed yet, but will be in the future. If you would like to check the integrity of the installer (recommended), you can verify the SHA256 checksum of the binary against the one displayed on the download page.

The command to verify the checksum in powershell is:

Get-FileHash -Algorithm SHA256 <path-to-installer>

The linux AppImage is a self-contained binary that can be run directly and stored anywhere. You may need to make it executable first:

chmod +x <path-to-appimage>

Requirements

  • A GPU with wgpu/WebGPU support (essentially any GPU from the last decade, on Vulkan, Metal, DirectX 12, or OpenGL).
  • A modern CPU with SSE2 support (essentially any CPU from the last decade).
  • Windows 10 or better, or a modern Linux distribution with a recent kernel and graphics drivers.
  • At least 2 GB of RAM, but 4 GB or more is recommended for larger surveys.

Interface Overview

NullCad’s main window is organized around a central canvas viewport, surrounded by panels for layers, properties, tools, and phase status.

  1. Menu bar — Standard menu bar for file operations, the view menu contains all windows for various features of the app.
  2. Phase tabs — switch between the four survey phases (Setup/Search, Boundary Model, Reinstatement, Drafting). Each phase has independent camera state and status tracking; see Survey Phases.
  3. Toolbar — grouped by category: Select, Draw, Modify, Survey, Measure, Surface & Drafting. See Drawing Tools and Modify Tools.
  4. Sign In — sign in to your Nullstrom account, the current open file path is also displayed here.
  5. Properties panel — inspect and edit the properties of the current selection.
  6. Layer panel — create, rename, delete, and organize layers with groups; per-layer color, visibility, lock state, and line type. See Layers.
  7. Tool Option panel — context-sensitive options for the currently active tool.
  8. Canvas View menu — Toggle visibility of certain elements on the canvas; plans, images, comparisons, labels
  9. Canvas viewport — the main drawing surface, rendered with a custom wgpu pipeline for precision at large coordinates (see Precision Handling).
  10. Status bar — coordinates under the cursor, active tool, snap state.

Theme

NullCad is designed around the Nullstrom Design System shared across Nullstrom products. The default theme is a dark mode with high contrast and color-coded elements. A light mode is also available from View -> Settings -> Display. The canvas background is black regardless of the theme, to maximize contrast with survey data.

Distraction-free mode

Press F11 to hide the side panels and show a floating toolbox — useful when you want the canvas to take up the full window.

Settings

Application settings (point size, selection threshold, colors, line weight, label display, camera sensitivity, autosave interval, and more) are available from the Settings menu, organized into categories such as Settings ▸ Interaction and Settings ▸ Labels.

Recent files

The File menu keeps a list of recently opened projects for quick access.

View bookmarks

Save up to 9 camera positions and recall them instantly:

ActionInput
Recall bookmark1–9
Set bookmarkCtrl+1–9

Navigation & Controls

ActionInput
PanMiddle mouse drag or Alt+Drag
ZoomScroll wheel (zooms toward cursor)
Zoom windowShift+Left Click Drag
Reset cameraReset Camera button
Zoom ExtentsE
Frame selectedF
View bookmarks1–9 to recall, Ctrl+1–9 to set

Panning and zooming are per-phase — each of the four survey phases keeps its own independent camera position, so switching phases doesn’t lose your place.

Editing

ActionInput
UndoCtrl+Z
RedoCtrl+Y or Ctrl+Shift+Z
Delete selectedDelete
Transform gizmo (move/rotate selection)W
Toggle consoleF12
Toggle Operation LogCtrl+H

Undo/redo operates on the full operation history — every mutation is recorded and reversible. See Operation System.

A full, searchable list of shortcuts is available from the in-app keyboard shortcuts help dialog, and summarized in Keyboard Shortcuts & Controls.

Selection

Basic selection

ActionInput
SelectClick on geometry
Multi-selectCtrl+Click
Rectangle selectClick and drag on empty canvas
Select allCtrl+A
Select all on layerShift+A

When clicking an object where multiple objects exist, a menu will appear to confirm the object you wish to select.

Selection uses an R-tree spatial index for efficient hit testing, so selecting and range-querying stays fast even on large datasets.

Hover highlighting

Geometry under the cursor is highlighted before you click, giving visual feedback about what a click will select.

Selection sets

Ctrl+G Save the current selection as a named set and restore it later with Ctrl+Shift+G — useful for repeatedly working with the same group of geometry (e.g. all boundary points, or all geometry on a particular layer).

Selection history

Navigate back Ctrl+[ and forward Ctrl+] through previous selections, similar to browser history.

Select Similar

Shift+S Filter and select geometry by type, layer, code, name, position, or length — useful for bulk operations like “select all points with code BNDRY” or “all lines on this layer.”

Context menus

Right-click on geometry or empty canvas for context-sensitive actions.

Drawing Tools

Geometry primitives

NullCad supports the following geometry primitives, all stored with full f64 precision:

  • Point
  • Line
  • Polyline
  • Polygon
  • Rectangle
  • Circle
  • Arc
  • Text

Draw toolbar

The Draw tool category provides: Point, Line, Polyline, Leader, Polygon, Text, Callout, Circle, Arc, and Rectangle.

Drawing tools respect the active snap configuration — clicks snap to endpoints, midpoints, intersections, grid points, and other configured snap targets by default.

Every draw operation is undoable

Like all mutations in NullCad, drawing goes through the operation system — every draw action is recorded, undoable, and tagged with the active survey phase and user if signed in.


Tool Details

Point

P

The Point tool creates a single point at the clicked location or coordinates can be entered manually in the tool options. Points can be used as survey points, reference points, or for snapping to other geometry.

Line

L

The Line tool creates a straight line between two points. Click to set the start point, then click again to set the end point. The line can be drawn at any angle, and snapping will help align it with existing geometry.

Polyline

Y

The Polyline tool creates a series of connected line segments. Click to set the first point, then click additional points to create segments. Right click and press Finish to end. Polylines are always open, and vertices can be edited after creation. To create a closed shape, use the Polygon tool.

Polygon

G

The Polygon tool creates a closed shape with three or more vertices. Click to set the first point, then click additional points to create the edges. Right click and press Finish to close the polygon. Polygons can be edited after creation, and snapping will help align edges with existing geometry.

Rectangle

Rectangle have 4 separate creation modes, available from the tool options when the tool is active.

  • 2-point — click two opposite corners to define the rectangle.
  • Centre-Corner — click the center point, then click a corner to define the rectangle.
  • 3-point — click three points to define the rectangle. Points 1 and 2 define one edge the 3rd defines height/width.
  • Corner+Dims — click one corner, then enter width and height in the tool options to define the rectangle.

Circle

Circles have 3 separate creation modes, available from the tool options when the tool is active.

  • 1-point — click the center point, then click a point on the circumference to define the radius or enter radius.
  • 2-point — click two points to define the diameter of the circle.
  • 3-point — click three points to define the circle. The circle will pass through all three points.

Arc

Arcs have 2 separate creation modes, available from the tool options when the tool is active.

  • 3-point — click three points to define the arc. The arc will pass through all three points.
  • Centre+Start+End — click the center point, then click the start and end points to define the arc.

Text

T

Text can be added to the canvas by clicking to set the top left anchor, in the tool options you can then set the content of the text and the size.

Once created, selecting the text will allow changing the properties or adding dynamic variables in the properties panel.

Formatting can be changed by double clicking the text to open it for editing, a toolbar will appear at the top of the canvas where you can change properties. The font dropdown will display Text Styles first and then all other system fonts available on the system.

Modify Tools

Basic modify tools

  • Move — translate selected geometry.
  • Rotate — rotate selected geometry around a point.
  • Scale — scale selected geometry.
  • Trim/Extend — trim or extend lines/polylines to a boundary. Any geometry with edges can be the boundary — lines, polylines, polygons, circles, arcs and rectangles — whether picked by hand or gathered by “use all visible geometry”.
  • Offset — create a parallel copy of a line or polyline at a fixed distance.

Transform gizmo

Press W to activate the transform gizmo on the current selection: a drag-based move/rotate handle with snapping, angle snap, and a relocatable pivot point. This is the fastest way to reposition or reorient a group of geometry interactively.

Explode

Press B to break compound geometry into simpler components — polygons become polylines, polylines become individual lines.

Vertex editing

Most basic geometry can be edited by pressing Space when the object is selected: add, remove, and move individual vertices after the geometry is created. Pressing Space again or Esc will end the edit mode.

Undo/redo

Every modify operation is recorded in the operation history and fully reversible with Ctrl+Z / Ctrl+Y. See Operation System.

Snapping

S

Snapping is a feature that allows you to easily align points to existing geometry or a grid. It is particularly useful for precision drawing and editing, ensuring that points are placed accurately relative to other elements in the design. Snapping can be configured at any time by pressing S.

NullCad supports several snap modes, which apply while using drawing and modify tools, all snaps below are passive and are computed constantly on hover if they are on:

  • Endpoint — snap to the start/end of a line or polyline segment or to a point object.
    • A green circle shows position of snap
  • Midpoint — snap to the midpoint of a segment.
    • A blue triangle shows the position of the snap
  • Nearest — snap to the closest point on a geometry.
    • An orange square shows the position of the snap
  • Grid — snap to a configurable grid spacing.
    • A yellow cross shows the position of the snap
  • Intersection — passively snap to the intersection of two line segments. This takes into account all visible geometry in view.
    • A red cross shows the position of the snap
  • Perpendicular — snap from a base point perpendicular to a line.
    • An unfilled orange square shows the position of the snap
  • Extension — snap to the extension of a line segment.
    • A purple unfilled diamond with a dashed line showing where the extension originates.
  • Angle constraint — constrain the next point to specific angle increments from the previous point.
    • The rubber band is constrained to the nearest angle and the angle is displayed near the end of the line

Active snap modes

At any time you may activate two different active snapping modes,

  • IntersectionI This manual intersection snap allows you to select the two lines you would like to compute the intersection for.
  • AverageV This snap allows you to select two or more points and compute the average position of those points. Press Enter to accept the computed average.

Configuring snapping

S

Snap settings (which modes are active, grid spacing, tolerance) are available from the snap configuration panel and persist with the document state.

You can change the tolerance for snaps at the bottom of the window.

Layers

Layer management

Nullcad has a robust layer management system. There are 3 types of layers available to the user:

  • Standard Layer
  • Layer Group
  • WMS Layer Pro

Layer properties

Standard layers have:

  • Visibility — Hide or show all geometry on the layer
  • Lock state — locked layers can’t be edited or selected
  • Label visibility — see Annotations & Labels
  • Colour — Set the colour of the layer’s geometry, the full ACI palette is available or pick from a custom RGB value
  • Name — You can use any layer name you like, it is not required that layers have unique names, nullcad stores a unique identifier for each layer under the hood.
  • Line weight — Set the line weight of all geometry on this layer. Uses the CAD standard millimetre denominations.
  • Line type — Set the line type of all the geometry on this layer. Select from built in or custom line types.
  • Delete button — Remove the layer. If the layer contains geometry you will be asked if you want to move the geometry or delete it along with the layer.

Phase-based filtering

Geometry is tagged with the survey phase it was created in (see Survey Phases), and the canvas filters what’s shown accordingly — you generally only see geometry relevant to the current phase, plus anything explicitly composed into a Drafting viewport.

WMS Layer

Pro Feature

WMS Layers allow for background maps to be displayed easily behind geometry. You can manage templates from View -> WMS Templates where you can set the properties of a WMS template, save and edit existing templates.

To add a template WMS layer to the canvas you must have a CRS set in File -> Document Properties to allow the system to understand the required transformation to apply to the fetched tiles.

Transformations are applied on the fly through proj4. It is not necessarily the most robust transformation and so should not be relied upon for survey data.

Fetched tiles are stored in an on-disk cache to speed up viewing and limit the amount of bandwidth use. If you need to clear the cache from stale data you can press the Clear Cache button at the bottom of the WMS Templates window.

Resources

Nullcad can import and view multiple formats of media separate from pure geometry, including PDFs and Images (JPG, PNG). These resources are stored directly in the save file rather than referenced externally. This keeps the project fully portable.

Resources can be dropped directly onto the canvas alongside geometry.

The Resource Manager

View -> Resources

This is where you import and view all resources attached to a document. Use the +Add Resources button to import resources from your file manager. It will allow selecting one or multiple images or PDFs to import. Once imported, save the document to write them to the archive.

Imported data files will also show in the resource manager.

The resource manager can be searched and filtered for various types. Drag Resources from the Resource Manager window to the canvas to add them, PDF’s will be added from the first page of the PDF, images show as you might expect, either will be scaled to a percentage of the view. Select a resource in the canvas to resize by dragging the handles and move them by dragging anywhere on the image/pdf.

You can change the page of the PDF in the properties panel and you can drop as many as you like of a single resource to show multiple pages of the same document.

You can copy/paste resources in the canvas. The pasted resource will occupy the same position and scale as the original, if you cant find it, its probably stacked on the original, drag it to a new position.

Codelists

Pro Feature

Codelists map survey codes to layers and layer properties (color, line type, line weight). During import, matching a geometry’s code against a codelist auto-creates and assigns the appropriate layer — useful for bringing in field data that uses a consistent coding scheme (e.g. from a data collector).

The Codelist Window

View -> Codelists

The codelist window allows you to manage codelists in the document. To create a new codelist, enter a name and press Create. If this is the first codelist it will be automatically set as the active codelist.

Adding codes to the codelist can be done by entering the code and layer in the fields above the list and pressing +Add. Once a code is added to the list you can set the properties of the layer.

Auto-manage layers

When a document has an active codelist, the auto-manage feature becomes available. It can be accessed by selecting the Auto-Manage Layers button above the layers in the layer panel.

When this mode is active, changing the code field on any geometry automatically moves the geometry to the layer defined in the codelist. You can also apply these mappings to all geometry by clicking the Apply to all geometry button in the layer panel.

Import/Export Codelists

Codelists are stored on the document or Document Template, if you are working from a fresh document you can import bulk codes from a CSV or from a previously exported codelist. The format required can be seen in the tool-tip of the import/export buttons.

TIN Surfaces

NullCad can build Triangulated Irregular Network (TIN) surfaces from selected points, using a Constrained Delaunay Triangulation, and display them as a triangle wireframe, as elevation contours, or both.

Creating a surface

  1. Activate the TIN Surface tool (SURVEY toolbar group). The TIN panel opens on the right.
  2. Select the points you want to triangulate (they must have Z values), then click Add Selected Points in the panel.
  3. Optionally add breaklines: select exactly two points from the list and click Add Breakline from Selection.
  4. Click Generate TIN Surface. At least 3 points with Z values are required, and the points must not all be collinear.

The surface is created as a single undoable operation on the active layer.

Display modes

Each surface has its own display settings, edited in the Properties panel and saved with the document:

  • Triangles — wireframe of the triangulation edges (default).
  • Contours — elevation contour lines derived from the mesh.
  • Both — edges and contours together.

Contours are controlled by two per-surface values:

  • Contour interval — vertical distance between levels, aligned to absolute multiples of the interval (an interval of 0.5 produces levels at …, 10.0, 10.5, 11.0, …).
  • Major every — every Nth level is a major contour and is drawn at twice the line weight.

Contours update live when the surface or its settings change, and they follow the display mode in drafting viewports and PDF export. If the interval is small enough to produce more than 2000 levels, contours are hidden and the Properties panel explains why.

Extracting contours

Extract Contours to Polylines (Properties panel) creates one polyline geometry object per contour line, on the surface’s layer, with the contour elevation stored as the polyline’s Z value. The extraction is a single undoable operation. Extracted polylines are ordinary geometry — they can be edited and exported, but they do not update if the surface changes.

Regenerating

Regenerate from Source Points (Properties panel) rebuilds the triangulation from the current positions and elevations of the points the surface was created from. Deleted source points are dropped (at least 3 must remain), breaklines are remapped, and the display settings are kept. The regeneration is undoable.

Non-destructive

Building a TIN surface never modifies the source points — the surface is a separate geometry object (TinSurface) that stores its own copy of the vertex data and references the source point IDs for regeneration.

Breaklines

  • Hard breaklines force triangle edges to follow the breakline exactly — used for discontinuities like retaining walls or building edges. Two hard breaklines may share endpoints but must not cross each other.
  • Soft breaklines are stored with the surface but do not affect the triangulation; they are reserved for future interpolation features.

Snapping and selection

Endpoint snap targets the TIN’s vertices; midpoint, nearest, perpendicular, and intersection snaps target its triangulation edges. Clicking selects the surface by its displayed linework (edges and/or contours), as does rectangle selection.

Export

  • PDF — the surface is drawn following its display mode, with major contours stroked heavier; this includes drafting viewports.
  • DXF — the surface exports as one 3DFACE entity per triangle with true per-vertex elevations, readable by other CAD packages.
  • Extracted contour polylines export like any other polyline (e.g. DXF polylines carrying their elevation).

Annotations & Labels

Text annotations

Add positioned text labels with configurable style and anchoring.

Callout annotations

Text with a leader line and configurable arrowhead — useful for pointing at a specific feature from a label placed nearby.

Point labels

Point geometry can be automatically labeled based on its metadata (code, description, name), following cartographic best practices to avoid label overlap.

Label content

  • Default format: {code} {description}
  • Supported placeholders: {code}, {description}, {name}
  • Empty labels (no content) are automatically hidden

Label placement

  • Labels are positioned at the point location, with collision detection to prevent overlaps.
  • Priority system: labels on the active layer are placed first.
  • After priority sorting, remaining ties are broken top-to-bottom.

Zoom behavior

Labels maintain a constant screen size as you zoom, rather than scaling with world geometry:

  • Target screen height: 12.0 px (configurable 8.0–24.0 px).
  • World size is clamped between a minimum (default 0.5) and maximum (default 50.0) so labels stop shrinking/growing past those bounds at extreme zoom.

Performance

  • Maximum label count (default 1000).
  • Only labels within the visible camera bounds are generated (frustum culling).
  • A minimum screen-height threshold prevents rendering labels too small to read.

Visibility controls

  • Global toggle: Settings ▸ Labels ▸ Enable Point Labels.
  • Per-layer toggle: the 🏷 button in the layer panel, next to the lock button. Labels also respect the layer’s own visibility.

Settings reference (Settings ▸ Labels)

SettingRangePurpose
Enable Point Labelson/offMaster toggle
Max Labels100–5000Cap on displayed labels
Target Screen Height8.0–24.0 pxDesired constant on-screen label height
Min World Size0.1–10.0Smallest label size when zoomed in
Max World Size10.0–200.0Largest label size when zoomed out
Min Screen Height4.0–20.0 pxCulling threshold for tiny labels
Label Formattemplate stringe.g. {code}: {description}

Usage

  1. Create points with a code and description (e.g. via CSV import or manually).
  2. Enable labels: Settings ▸ Labels ▸ Enable Point Labels.
  3. Toggle per-layer visibility with the 🏷 button in the layer panel.
  4. Customize the label format string, e.g. {code}: {description}.

Text Styles

A text style is a named preset for text objects — it bundles font family, bold/italic, default height, colour, and line spacing under a name like “Road Names” or “Lot Numbers”, as traditional CAD does. Styles are stored in the document and save/load with templates, so an office standard set travels with your drawings.

Every new document starts with two styles matching the built-in fonts:

  • Standard — Inter
  • Monospace — the bundled Roboto Mono

Applying a style stamps its properties onto the text object at that moment. Text objects keep no reference back to the style, so:

  • Editing a style later does not restyle existing text.
  • Deleting a style leaves existing text exactly as it is.

To restyle existing text, re-apply the (edited) style to it.

Managing styles

Open the manager from View -> Text Styles. Each style is a row you can edit in place:

  • Name — what appears in the font dropdown.
  • Font — Inter and Monospace first, then every font installed on the machine (see Fonts below).
  • B / I — bold and italic toggles.
  • Height — the default text height, in world units (metres for a survey drawing) — unlike line type patterns, which are paper millimetres.
  • Color — full ACI palette or a custom RGB value.
  • Spacing — line spacing multiplier for multi-line text (0.5–3.0, 1.0 = normal).

Create a style by typing a name at the top and clicking Create (it starts as Inter with default properties); delete one with ✕.

Applying a style

Double-click a text object (or create one with the Text tool) to enter text editing. The font dropdown in the text-edit toolbar lists the document’s styles at the top — each with a summary of its font, weight, and height — followed by the raw font families. Picking a style stamps all of its properties onto the text, including the height; picking a bare font family changes only the font.

Fonts

Font families come from three sources, scanned once at launch:

  1. Bundled — Inter and Roboto Mono ship inside NullCad and render identically on every machine.
  2. User fonts — any font file placed in the fonts folder of NullCad’s configuration directory:
    • Linux: ~/.config/nullcad/fonts
    • Windows: %APPDATA%\nullcad\fonts
  3. System fonts — everything installed on the machine.

Fonts installed while NullCad is running are picked up on the next launch.

If a document asks for a font that isn’t available on the current machine, the text renders in a fallback font rather than disappearing. For drawings that move between machines, prefer the bundled families or install the same fonts (e.g. via the user fonts folder) everywhere the drawing is opened.

Templates

Templates

Most settings and document properties can be saved to a template including:

  • Layers
  • CRS
  • Scale Factor
  • Codelists
  • WMS Templates
  • Linetypes

Save a template through File -> Save As Template

You can then set a default template in View -> Settings -> Templates. This template will be used whenever you start a new document.

Line Types

Every piece of geometry is drawn with a line type — either one of the built-in patterns or a custom linetype defined in TOML. Line types can be set in two places:

  • Per layer — the Line type dropdown in the layer panel applies to all geometry on the layer (see Layers).
  • Per geometry — the Linetype dropdown in the properties panel overrides the layer setting for the selected geometry. Choosing Default in the layer dropdown lets each geometry use its own setting.

Built-in line types

Continuous (the default), Dashed, Dotted, Dash-Dot, Dash-Dot-Dot, Center, Hidden, and Phantom.

Custom line types

Nullcad ships a default library of survey-oriented linetypes (Boundary, Easement, Traverse, Wire Fence, Water, Gas, Sewer, and more) and lets you define your own in a TOML file. Custom linetypes can include text and symbols repeated along the line — e.g. a water main drawn as ———— W ———— W ————.

  • Import: File -> Import -> Linetypes (TOML). If an imported name matches an existing linetype, a conflict dialog asks whether to overwrite the existing definition or skip the incoming one. Overwriting keeps existing geometry pointing at the updated definition.
  • Export: File -> Export -> Linetypes (TOML) writes the document’s custom linetypes to a file you can share or re-import elsewhere.

Custom linetypes are stored in the document itself (and in templates), so a drawing always carries the definitions it uses.

The TOML format

[linetypes.myline]                # Required namespace; the key must be unique
name = "My Line"                  # Required; shown in the linetype dropdowns
description = "A test linetype"   # Optional, shown alongside the name
pattern = [                       # Required: the repeating pattern
    { stroke = 3.0 },             # Visible dash, 3 mm long
    { gap = 2.0 },                # Invisible break, 2 mm long
    { text = "E", font_size = 2.5 },
    { symbol = "M -1 -1 L 1 1", scale = 1.0 },
]

A file can contain any number of [linetypes.<key>] tables. The pattern list repeats along the whole length of the line.

All dimensions are in millimetres of paper at 1:1, scaled on screen and in output by the current linetype scale — a 3.0 stroke prints 3 mm long at 1:1, 3 m ground at 1:1000.

Pattern elements

Each entry in pattern is one of five element types, chosen by which keys it contains:

ElementKeysNotes
StrokestrokeVisible dash; the value is its length in mm.
GapgapInvisible break; the value is its length in mm.
Dotdot = trueA point marker occupying 0.5 mm of pattern.
Texttext, font_size, rotationText along the line. font_size is in mm (default 2.5); rotation is in degrees relative to the line direction (default 0).
Symbolsymbol, scale, rotation, keep_strokeA small vector shape (see below). scale defaults to 1.0, rotation to 0.

Only the keys shown are recognised — e.g. scale on a text element is silently ignored; use font_size.

Symbols

The symbol value is a path in a small subset of SVG path syntax — straight lines only:

  • M x y — move to (absolute)
  • L x y — line to (absolute)
  • m dx dy — move to (relative)
  • l dx dy — line to (relative)

Numbers are whitespace-separated; commas are not accepted — write "M -1 -1 L 1 1", not "M -1, -1, L 1, 1". Curves and arcs are not supported. Coordinates are in symbol units around the line: the path is multiplied by scale, so at scale = 1.0 a coordinate of 1 is 1 mm from the line. Some examples:

{ symbol = "M -1 -1 L 1 1" }                # single tick /
{ symbol = "M -1 -1 L 1 1 M -1 1 L 1 -1" }  # X marker
{ symbol = "M -1 -1 L 1 -1 L 1 1 L -1 1 L -1 -1" }  # square

By default a symbol replaces a section of the line: it occupies a slot 2 × scale mm wide, punched out of the pattern like a gap. Set keep_stroke = true to instead draw the symbol on top of a continuous line without consuming any pattern length — right for tick marks along an unbroken line, as in the default Building linetype:

[linetypes.building]
name = "Building"
pattern = [
    { stroke = 3.0 },
    { symbol = "M 0 0 L 1 1", scale = 1.0, keep_stroke = true },
]

Linetype scale

Pattern dimensions are paper units, so how large they appear depends on the linetype scale, set per survey phase from the 1:… indicator in the status bar:

  • Manual — type a scale denominator (e.g. 1:500). Pick the scale you intend to plot at and the plotted pattern matches its definition in mm.
  • Link to zoom — the scale is recomputed from the current zoom level and your screen PPI (Settings › Display), so patterns keep a constant on-screen size as you zoom. The status bar shows a link icon while active.

Troubleshooting

  • “No linetypes found in file” — the file has no [linetypes.<key>] tables; check the namespace spelling.
  • Import fails with a parse error — the console (View -> Console) reports the offending line. Common causes: a missing pattern, a missing name, or commas inside a symbol path.
  • Pattern looks solid or invisible — the linetype scale for the current phase is too small or too large for the geometry; adjust it from the status bar.

Document Properties

The document properties should be the first thing checked and filled when starting a new job. It contains properties and settings that affect the rest of job.

File -> Document Properties

Combined Scale Factor

Nullcad is designed around the idea that incoming data from a controller is in grid coordinates, and final plans and data are required to be coordinated. Conversely, distances are required to be plane distances and entered distances from existing plans are also in plane. Traditionally, data is scaled to plane after import from a controller for calculations and surveyors must rescale data back to grid to attain final coordinates.

Nullcad solves this by keeping your data in grid and using a global CSF to dynamically scale entered distances back to grid and show or label distances on geometry in plane. The scale factor can be entered manually in the General tab of the Document Properties window. You can also calculate a CSF by selecting and existing point in your document, normally a known control point.

Note: when calculating a CSF make sure the point used has a Z/Height.

NullCad uses the following formula for MGA (Map Grid of Australia) / UTM projections.

Formula

CSF = PSF × HSF

Where:

  • CSF = Combined Scale Factor
  • PSF = Point Scale Factor (accounts for map projection distortion)
  • HSF = Height Scale Factor (accounts for elevation above the ellipsoid)

Point Scale Factor (PSF)

PSF = 0.9996 + 1.23 × (E - 500000)² × 10⁻¹⁴

Where:

  • E = Easting coordinate (metres)
  • 500000 = False easting (central meridian offset for UTM/MGA zones)
  • 0.9996 = Central meridian scale factor (k₀) for UTM

PSF equals exactly 0.9996 at the central meridian (E = 500,000m) and increases as you move east or west.

Height Scale Factor (HSF)

HSF = 1 - (H × 0.1571 × 10⁻⁶)

Where:

  • H = Ellipsoidal height (metres)
  • 0.1571 × 10⁻⁶ ≈ 1 / 6,371,000 (approximation of 1/Earth radius)

HSF reduces distances as elevation increases, since higher points are further from Earth’s centre.

Where to configure it

The active CSF is set in the Document Properties and applied by all tools that take a distance.

Caveat

This formula is a simplified approximation suitable for most surveying work within a single UTM/MGA zone. For high-precision geodetic work spanning zone boundaries or requiring rigorous error bounds, use the full Transverse Mercator equations instead.

Survey Phases

NullCad organizes work into four phases, each with independent camera state and status tracking. Geometry and operations are tagged with the phase they’re created in, so switching phases filters what’s shown and keeps work-in-progress in one phase from cluttering another.

PhasePurpose
Setup/SearchA virtual desk for laying out plans, research, and annotations before modeling begins.
Boundary ModelBuilding the surveyable model from historical plans. This is the default phase.
ReinstatementComparing field measurements against the boundary model and adjusting.
DraftingFinalizing the plan for submission — page proxies, viewports, PDF export.

Switching phases

Use the phase tabs at the top of the window. Each phase remembers its own camera pan/zoom position independently, so returning to a phase puts you back where you left off.

Why phase-based?

Cadastral survey work naturally moves through stages — research, modeling, field verification, and final drafting — each with different working material and different geometry. Tagging geometry by phase lets each stage stay visually uncluttered by the others, while still keeping everything in one document with a single operation history and undo/redo stack.

Phase status tracking

Each phase tracks its own completion status, useful for keeping a survey project’s overall progress visible at a glance.

  • Traverse Tool — used mainly in Boundary Model, to build the model from bearings and distances.
  • Comparison Tool — used in Reinstatement, to compare field measurements against the model.
  • Page Proxies & Viewports — used in Drafting, to lay out final sheets.

Traverse Tool

The Traverse tool builds connected survey traverses by entering bearings and distances, rather than clicking points on the canvas — the standard way boundary geometry is specified on a plan of survey.

Basic use

  1. Select the Traverse tool from the Survey tool category.
  2. Enter a starting point (or snap to an existing one).
  3. Enter a bearing and distance for each subsequent leg.
  4. Each leg is added to a connected polyline as you go.

Bearing format

Bearings are entered and displayed in degrees-minutes-seconds (DMS), rounded to the nearest second — the surveying standard — not decimal degrees.

The default input is HP notation (DDD.MMSS), where the digits after the decimal point encode minutes and seconds rather than a decimal fraction of a degree:

InputParsed as
123.2312123°23’12“
45.3045°30’00“
9090°00’00“
45 30 1545°30’15“ (space-separated DMS also accepted)

To enter true decimal degrees instead, prefix the value with d (e.g. d45.5 → 45.5° = 45°30’00“). Append * to reverse a bearing by 180°.

Scale factor support

The Traverse tool supports a Combined Scale Factor (CSF) for grid-to-ground distance conversion, so entered distances can be treated as either ground distances or grid distances depending on how your survey data was recorded. See Combined Scale Factor for the formula and when to apply it.

Where this fits in the workflow

The Traverse tool is most commonly used in the Boundary Model phase, building the surveyable model from bearings and distances taken off historical plans. See Survey Phases.

Comparison Tool

The Comparison tool compares field measurements against the boundary model, using bearing/distance input — the core of the Reinstatement phase (see Survey Phases).

Purpose

After building a boundary model from historical plans, field survey work verifies that model against measurements taken on the ground. The Comparison tool records those field bearing/distance observations against model points and stores the comparison results with the document.

Comparison storage

Comparisons are stored in the document (document/comparison.rs), so comparison history is preserved with the project and available for review or reporting alongside the rest of the survey data.

Bearing format

As with the Traverse tool, bearings are entered in DMS/HP notation (DDD.MMSS), not decimal degrees. The comparison table displays the survey bearing, measured bearing, and the delta between them each rounded to the nearest arcsecond (e.g. 045° 30' 00") rather than showing fractional seconds, keeping the table readable.

Page Proxies & Viewports

The Drafting phase (see Survey Phases) is where a survey project becomes a finished plan for lodgement. Two geometry types drive this: page proxies and viewports.

Page proxies

A page proxy lays out a drafting sheet at a chosen draw scale, on one of the standard paper sizes:

  • ISO A-series (A0–A4)
  • US (Letter, Legal, Tabloid, …)
  • ANSI (A–E)
  • ARCH (A–E)

Each page proxy becomes one page in the exported PDF (see PDF Export). A page can be assigned a sheet template (a title block) — see below.

Sheet templates

A sheet template supplies the title-block linework and text placed on top of a page’s content, with substitutable fields like <PROJECT>, sheet number, and sheet name.

Sheet templates can be imported directly from a DXF file’s paper-space layout: NullCad recovers the layout’s true physical paper size from the DXF’s embedded plot-settings (not just its arbitrary limits/extents), and rescales non-millimeter content to fit. INSERT block references (common for real title blocks) are expanded recursively.

Assigning a template to a sheet resizes the page to the smallest standard paper size that fully contains the template, so the template’s linework — laid out in its own physical millimeter coordinates — always ends up inside the visible page rather than centered against a mismatched size.

The Sheet Manager (accessible from the Drafting phase) lists all sheets in the document, lets you assign templates, fill in title-block field values, and reorder/renumber sheets.

Viewports

A viewport is a window placed on a Drafting-phase page that displays content from another phase (most commonly Boundary Model), with its own independent pan, zoom, and rotation — similar to a viewport in traditional CAD software. This is how survey/model geometry actually ends up on a printed sheet: you draft the page and title block in the Drafting phase, then open one or more viewports onto the phase that holds the real geometry.

Draw scale

Each page proxy has its own draw scale, so different sheets in the same document can be laid out at different scales (e.g. an overview sheet at 1:1000 and a detail sheet at 1:200). Linetype patterns (dashes, dots) on the Drafting-phase canvas follow whichever page’s draw scale the camera is currently nearest to, so on-screen dash spacing matches what will actually print on that sheet.

PDF Export

NullCad exports drafting sheets as a multi-page vector PDF — geometry is written as real vector paths (and text as glyph outlines), not a raster image, so the output stays crisp at any zoom and prints cleanly.

What gets exported

Each page proxy in the document becomes one PDF page:

  1. Page content — geometry sharing the page’s phase and intersecting its bounds is transformed from world meters to paper millimeters at the page’s draw scale, styled per layer (color, line weight, line type), and clipped to the sheet.
  2. Viewport content — geometry composed through any viewports on the page, from whichever phase each viewport targets, at that viewport’s own pan/zoom/rotation.
  3. Sheet template — the assigned title block, rendered on top, with its substitutable fields (<PROJECT>, sheet number/name, etc.) filled in.

Pages are ordered by (sheet number, name), so legacy documents (where every sheet number is 0) keep their existing name order.

Exporting

Open the PDF export dialog from the Sheet Manager or File ▸ Export ▸ PDF. You can choose which pages to include and export options such as monochrome output.

Line types in the exported PDF

Custom linetype patterns (dashes, dots, center lines, etc.) are resolved against the project’s linetype library and interpreted as paper millimeters, independent of the page’s draw scale — so a dash pattern defined for a 1:500 sheet looks the same physical size as the same pattern on a 1:100 sheet.

Text

Text is rendered as filled glyph outlines rather than PDF text objects, so the exported PDF doesn’t depend on font availability on the viewer’s system and renders identically everywhere.

Supported Formats

Native (pure Rust — always available)

FormatExtensionNotes
ESRI Shapefile.shpIndustry-standard GIS vector format
GeoJSON.geojson, .jsonWeb-friendly geographic data format; non-finite coordinates are rejected on import
DXF.dxfAutoCAD Drawing Exchange Format, with native Circle/Arc support; non-finite coordinates are rejected on import
CSV.csvPoint data with configurable column mapping (import) and column/format selection (export) — see CSV Export

GDAL (optional — requires the gdal feature)

FormatExtensionNotes
KML.kmlKeyhole Markup Language, for Google Earth
GeoPackage.gpkgModern SQLite-based GIS format
MapInfo TAB.tabMapInfo native format
OpenFileGDB.gdbESRI File Geodatabase

See Building from Source for how to build with GDAL support.

Coordinate reference systems

All formats support CRS handling with automatic transformation options via proj4rs.

DXF import notes

  • BYBLOCK colors fall back to black (the source block’s actual color isn’t always recoverable through the parsing crate used).
  • When importing DXF sheet templates (paper-space layouts, for use as drafting title blocks), the true physical paper size is recovered from the DXF’s plot-settings where possible; binary DXF files fall back to a layout-limits/content-extents heuristic.

Web viewer bundle (.ncweb)

A separate, purpose-built export format for the companion field/phone viewer — see Web Viewer Bundle.

CSV Export

NullCad supports exporting geometry to CSV with customizable column options, complementing CSV import.

Column selection

ColumnDescription
NamePoint number or label (auto-generated as PT1, PT2, … if empty)
Vertex IndexIndex of a vertex within a multi-vertex geometry (lines/polylines)
XEasting or longitude
YNorthing or latitude
Z / HeightElevation or height (defaults to 0 if unset)
CodeFeature code for categorization
DescriptionDetailed description or notes
LayerLayer name

Format options

  • Coordinate precision: 0–10 decimal places, defaults to 6.

Geometry handling

By default, only Point geometry is exported.

Enabling export non-point geometries adds:

  • Lines — all vertices (start and end), one row each.
  • Polylines — all vertices, one row each.
  • Polygons — the centroid, as a single row.
  • Circles, Arcs, Rectangles — the center point, as a single row.
  • Text — the insertion point, as a single row.

Export behavior

  • Selection-aware: if geometry is selected, only the selection is exported; otherwise all active (non-deleted) geometry is exported.
  • Auto-generated names: points with an empty name get PT1, PT2, etc.
  • Default height: Z/Height defaults to 0 (rather than being left empty) when unset.
  • Multiple rows per geometry: exporting a line/polyline with export of non-points enabled produces one row per vertex, all sharing the same metadata (name, code, description, …).

Usage

  1. Select geometry to export (optional — leave nothing selected to export everything).
  2. File ▸ Export ▸ CSV…
  3. Choose which columns to include, and optionally enable “Export non-point geometries.”
  4. Export, then choose the output file location.

Default configuration

Enabled by default: Name, X, Y, Z/Height, Code, Description, 6 decimal places of precision.

Disabled by default: Vertex Index, Layer, non-point geometry export.

CSV format

Standard RFC 4180: header row, comma-separated fields, fields containing commas are quoted, empty fields are unquoted empty strings.

Example — points only (default)

name,x,y,z,code,description
PT1,500000.123456,4500000.654321,123.450000,CTRL,Control Point
PT2,500100.234567,4500100.765432,124.560000,BNDRY,Boundary Marker
PT3,500200.345678,4500200.876543,0.000000,TOPO,Topographic Point

Example — line vertices with vertex index

name,vertex_index,x,y,code
LINE1,0,100.000000,200.000000,BOUND
LINE1,1,150.000000,250.000000,BOUND
LINE1,2,200.000000,300.000000,BOUND

Example — auto-generated names

name,x,y,z
PT1,100.000,200.000,0.000
PT2,300.000,400.000,0.000

See also

Web Viewer Bundle

NullCad can export a self-contained .ncweb bundle for a companion browser/phone viewer — useful for reviewing a survey project in the field without running the full desktop application.

What’s in the bundle

.ncweb is a ZIP archive containing:

  • manifest.json — CRS, extent, camera position, layer list.
  • features.geojson — geometry as GeoJSON, with styles resolved (colors, line weights, etc.) at export time so the viewer doesn’t need to replicate NullCad’s full styling logic.
  • resources/ — embedded resources (e.g. reference images) needed by the viewer.

Exporting

File ▸ Export ▸ Web Viewer Bundle…, then choose an output location for the .ncweb file.

The viewer

The companion viewer is a TypeScript Progressive Web App (PWA), designed for field/phone use — it opens a .ncweb bundle and renders the exported geometry with the resolved styles, without needing network connectivity once loaded.

Keeping exporter and viewer in sync

The .ncweb format is produced by the Rust exporter (src/gis_io/native/web_bundle.rs) and consumed by the separate viewer/ TypeScript project. Because the format is shared between two independently built codebases, changes to the bundle’s schema need to land on both sides together.

Lua Plugins

NullCad can be extended with Lua 5.4 plugins. Plugins can add menu commands, interactive canvas tools, panels and dialogs, and automation hooks that react to application events. Every document mutation a script makes goes through the normal operations system, so plugin edits are undoable and appear in the audit trail like hand-drawn geometry.

Installing plugins

Plugins live in the NullCad config directory:

PlatformLocation
Linux~/.config/nullcad/plugins/
Windows%APPDATA%\nullcad\plugins\
macOS~/Library/Application Support/nullcad/plugins/

Two layouts are supported:

  • Single file — drop my_plugin.lua directly in plugins/.
  • Directory — a folder containing plugin.toml and an entry script:
# plugins/survey-helpers/plugin.toml
name = "Survey Helpers"
id = "survey-helpers"        # optional, defaults to the folder name
version = "0.1.0"
description = "Point grids, selection reports"
author = "You"
entry = "init.lua"           # optional, defaults to init.lua

Plugins load on startup. Use Plugins ▸ Reload Plugins after editing a script, and Plugins ▸ Plugin Manager… to enable/disable plugins or see load errors. Plugins ▸ Run Script… executes a one-off .lua file without installing it (useful for batch automation).

A minimal plugin

-- plugins/hello.lua
nc.register_command{
    id = "hello",
    title = "Say Hello",
    run = function(ctx)
        ctx:toast("Hello from Lua!", "success")
    end,
}

This adds Plugins ▸ hello ▸ Say Hello to the menu bar.

The nc global

Every plugin runs in its own Lua state with the nc table installed:

ItemPurpose
nc.versionNullCad version string
nc.ctxApplication context (see below)
nc.register_command{...}Add a menu command
nc.register_tool{...}Add an interactive canvas tool
nc.register_panel{...}Add a toggleable panel
nc.on(event, handler)Subscribe to an application event

All callbacks receive ctx (the same object as nc.ctx) as their first argument.

Commands

nc.register_command{
    id = "count",                 -- required, unique within the plugin
    title = "Count Geometry",     -- menu label (defaults to id)
    run = function(ctx) ... end,  -- required
}

Tools

Tools receive snapped canvas clicks in world coordinates. Return true from on_click to finish the tool (the app returns to selection mode); return false/nothing to keep receiving clicks. Tool state is just Lua upvalues.

local first = nil
nc.register_tool{
    id = "two-point",
    name = "Two Point Line",
    instructions = "Click start point, then end point",
    on_click = function(ctx, x, y)
        if not first then
            first = {x = x, y = y}
            return false
        end
        ctx:create_line{start_x = first.x, start_y = first.y, end_x = x, end_y = y}
        first = nil
        return true
    end,
}

Registered tools appear in the plugin’s menu; activating one behaves like any built-in tool (Esc cancels, snapping applies).

Panels and dialogs

UI is declarative: a list of widget tables rendered by the app. Button clicks call your on_event handler with the button id and the current values of all input widgets (keyed by widget id).

Widget types:

{type = "heading",   text = "Section"}
{type = "label",     text = "Static text"}
{type = "separator"}
{type = "text",      id = "name", label = "Name",    value = "default"}
{type = "number",    id = "dist", label = "Distance", value = 10.0}
{type = "checkbox",  id = "flag", label = "Enabled",  value = true}
{type = "select",    id = "mode", label = "Mode", options = {"A", "B"}, value = "A"}
{type = "button",    id = "go",   label = "Go"}

Panels are registered once and toggled from the plugin’s menu (or with ctx:open_panel(id) / ctx:close_panel(id)); update their contents with ctx:update_panel(id, widgets).

nc.register_panel{
    id = "quick-point",
    title = "Quick Point",
    widgets = {
        {type = "number", id = "x", label = "Easting",  value = 0.0},
        {type = "number", id = "y", label = "Northing", value = 0.0},
        {type = "button", id = "create", label = "Create Point"},
    },
    on_event = function(ctx, event, values)
        if event == "create" then
            ctx:create_point{x = values.x, y = values.y}
        end
    end,
}

Dialogs are opened from any callback with ctx:show_dialog. Return true from the handler to close the dialog; the window’s ✕ also closes it.

ctx:show_dialog{
    title = "Grid Options",
    widgets = {
        {type = "number", id = "rows",    label = "Rows",    value = 5},
        {type = "number", id = "spacing", label = "Spacing", value = 10.0},
        {type = "button", id = "ok",     label = "Create"},
        {type = "button", id = "cancel", label = "Cancel"},
    },
    on_event = function(ctx, event, values)
        if event == "ok" then make_grid(ctx, values) end
        return true  -- close on any button
    end,
}

Events (automation)

nc.on("document_saved", function(ctx, e)
    ctx:log("Saved to " .. e.path)
end)
EventPayload
document_opened{path}
document_saved{path}
document_new{}
operation_applied{description}
selection_changed{ids, count}
phase_changed{phase}

Events are delivered once per frame, after the mutation completes. Operations performed inside an operation_applied handler do not re-trigger the event (no feedback loops).

ctx reference

Coordinates are world meters (f64). Geometry and layer ids are UUID strings. Errors raise Lua errors — wrap calls in pcall if you want to recover.

Reading

MethodReturns
ctx:document_info(){project_name, file_path, geometry_count, layer_count, current_phase, active_layer_id, ...}
ctx:current_phase()"SetupSearch" | "BoundaryModel" | "Reinstatement" | "Drafting"
ctx:list_layers(){layers = {{id, name, visible, locked, color, order}, ...}}
ctx:list_geometry{layer_name=, geometry_type=, limit=}{count, items = {{id, type, name, layer_name, z, summary}, ...}} (all filters optional)
ctx:get_geometry(id)Full record incl. geometry table (e.g. {type = "Point", x, y}; Text/Rectangle include rotation_degrees, CCW from east)
ctx:selection()Array of selected geometry ids

Creating geometry

All creators accept optional layer_id/layer_name (defaults to the default layer), name, description, and (where meaningful) z. They return the new geometry’s id.

ctx:create_point{x=, y=, z=}
ctx:create_line{start_x=, start_y=, end_x=, end_y=}
ctx:create_polyline{points = {{x=, y=}, ...}}          -- ≥ 2 points
ctx:create_polygon{points = {{x=, y=}, ...}}           -- ≥ 3 points
ctx:create_circle{center_x=, center_y=, radius=}
ctx:create_arc{center_x=, center_y=, radius=, start_angle=, end_angle=}
ctx:create_rectangle{corner1_x=, corner1_y=, corner2_x=, corner2_y=}
ctx:create_text{x=, y=, content=, height=}
ctx:create_layer{name=, color="#RRGGBB"}               -- returns layer id

Modifying

MethodEffect
ctx:delete(id)Soft-delete a geometry object (undoable)
ctx:move_geometry(ids, dx, dy)Translate the given ids by a delta
ctx:rotate_geometry(ids, center_x, center_y, angle_degrees)Rotate around a center point, clockwise degrees (surveying convention, same as the Rotate tool)
ctx:set_selection(ids) / ctx:clear_selection()Change the selection

Feedback & UI

MethodEffect
ctx:toast(message, level?)Toast notification ("info", "success", "warning", "error")
ctx:log(message, level?)Write to the console (F12), attributed to the plugin
ctx:show_dialog{title=, widgets=, on_event=}Open a dialog
ctx:update_panel(id, widgets)Replace a panel’s widgets (values with matching ids survive)
ctx:open_panel(id) / ctx:close_panel(id)Show/hide a registered panel

Notes & limitations

  • Scripts run on the UI thread: a long loop blocks the interface. Keep per-callback work modest.
  • ctx is only valid while NullCad is calling into your script (load, callbacks). Don’t stash it for use from Lua coroutines/timers — there are none anyway.
  • Lua’s standard library is available (math, string, table, io, os), so scripts can read/write files for import/export automation.
  • Full examples live in docs/examples/plugins/ in the repository: survey-helpers/ (commands, tools, panels, events) and align-text.lua (rotate a text object to match a clicked line direction).

MCP Server

NullCad includes an in-process Model Context Protocol (MCP) server (HTTP+SSE), letting an AI agent read and create geometry in the currently open document.

How it works

The MCP server runs as a background tokio task inside the application. Mutations requested by an agent are funnelled back to the egui main thread via a channel, so they go through the same operation system as any other edit — every agent-driven change is undoable and recorded in the audit trail, exactly like Lua plugin edits or manual drawing.

Enabling the server

The MCP server’s settings (enable/disable, port) are available in the application settings and persist with the document.

Connecting an agent

Once enabled, point an MCP-compatible client at the server’s HTTP+SSE endpoint to give an agent access to:

  • Reading document info, layers, and geometry.
  • Creating and modifying geometry (points, lines, polylines, polygons, circles, arcs, rectangles, text).
  • Reading and changing the current selection.

The tool surface mirrors the Lua plugin API’s ctx methods (see Lua Plugins) — both are implemented against the same underlying operation builders (mcp/tools.rs), so behavior (units, coordinate conventions, rotation direction) is consistent between the two integration paths.

Why in-process?

Running the MCP server inside the application (rather than as a separate process talking to a file) means an agent is always working against the live, in-memory document state — including unsaved changes — and its edits appear immediately in the UI, just like a human’s.

Keyboard Shortcuts & Controls

A full, searchable list is available in-app via the keyboard shortcuts help dialog. This page summarizes the defaults.

ActionInput
PanMiddle mouse drag
ZoomScroll wheel (zooms toward cursor)
Reset cameraReset Camera button
Distraction-free modeF11
View bookmarks1–9 to recall, Ctrl+1–9 to set

Selection

ActionInput
SelectClick on geometry
Multi-selectCtrl+Click
Rectangle selectClick and drag on empty canvas
Select allCtrl+A

Editing

ActionInput
UndoCtrl+Z
RedoCtrl+Y or Ctrl+Shift+Z
Delete selectedDelete
ExplodeB
Transform gizmo (move/rotate selection)W
Toggle consoleF12

Tool categories

CategoryTools
SelectDefault selection mode
DrawPoint, Line, Polyline, Leader, Polygon, Text, Callout, Circle, Arc, Rectangle
ModifyMove, Rotate, Scale, Trim/Extend, Offset, Transform Gizmo
SurveyTraverse, Comparison
MeasureDistance and bearing measurement (bearing shown in DMS, rounded to the nearest second)
Surface & DraftingTIN Surface, Page Proxy, Viewport

See also: User Guide for what each tool does.