plan.json
plan.json is the derived stitch list in an open, machine-neutral form. It
exists so that a third party can produce DST, PES, EXP, JEF or anything else
without understanding the editable model. If you are writing an exporter,
this is the only page you need.
It is optional. Exported .hoop files carry it; an application’s own library
saves commonly do not, because it can always be regenerated. Readers MUST
handle its absence.
Coordinate system
Section titled “Coordinate system”- Unit: millimetres, floating point.
- Origin: the hoop centre.
- y points up. Most machine formats have y pointing down; converting is a sign flip, and forgetting it is the single most common porting bug.
{ "stitches": [ { "position": { "x": 11.844811, "y": 1.330744 }, "function": "jump" }, { "position": { "x": 12.100000, "y": 1.500000 }, "function": "stitch" } ], "commands": [ { "kind": { "colorChange": { "index": 3 } }, "beforeStitchIndex": 0 }, { "kind": { "trim": {} }, "beforeStitchIndex": 505 } ], "colorTable": [ { "red": 47, "green": 48, "blue": 50, "catalogId": "madeira-polyneon", "code": "1800", "name": "Black" } ], "objectRanges": [ { "objectID": "63C5BD58-4BF0-434B-AE1A-E1018D8A9192", "start": 0, "end": 502 } ], "stats": { "stitchCount": 2214, "jumpCount": 9, "trimCount": 8, "colorChangeCount": 4, "bounds": { "minX": -17.697304, "minY": -20.741376, "maxX": 17.492767, "maxY": 21.952183 } }}stitches
Section titled “stitches”An ordered array of needle positions. Each entry is an absolute position — there are no deltas anywhere in this format, which is what keeps it immune to the drift that plagues delta-encoded machine formats.
function is one of:
| Value | Meaning |
|---|---|
stitch | Needle down. A normal stitch. |
jump | Pen-up movement. The machine moves without stitching. |
travel | A needle-down connecting run between parts of a design. Sewn exactly like a normal stitch. |
travel exists so that tools which care can tell a structural connection from
design stitching — for example to hide or re-route it. Readers that do not
distinguish it MUST treat travel as stitch. Treating it as a jump would
produce a file that skips stitches the design needs.
commands
Section titled “commands”Machine commands anchored before the stitch at beforeStitchIndex. Several
commands may share an index; they apply in array order.
| Kind | Payload | Meaning |
|---|---|---|
colorChange | { "index": Int } | Change to the thread at that index in colorTable. |
trim | {} | Cut the thread. |
stop | {} | Pause the machine without a thread change. |
The JSON shape is a single-key object naming the kind, with the payload as its
value — including for payload-less kinds, which encode as an empty object
({"trim": {}}).
colorTable
Section titled “colorTable”The threads the plan refers to, in plan order.
| Field | Type | Meaning |
|---|---|---|
red, green, blue | 0–255 integers | Display colour. |
catalogId | string, optional | Thread catalogue identifier, e.g. madeira-polyneon. |
code | string, optional | Catalogue number, e.g. 1800. |
name | string, optional | Human-readable name, e.g. Black. |
The three optional fields are what a machine format cannot carry. DST has no colours at all; PES and JEF map to a manufacturer’s fixed palette. Here the identity survives, so a worksheet can say Madeira Polyneon 1800 Black rather than the dark one.
Any of them may be null for a colour picked freely rather than from a
catalogue. Only the RGB triple is guaranteed.
objectRanges
Section titled “objectRanges”Maps regions of the stitch list back to the design objects that produced them.
{ "objectID": "63C5BD58-…", "start": 0, "end": 502 }start is inclusive, end exclusive, both indexing stitches. Ranges are in
stitch order and, taken together, cover the whole array.
This is what makes a stitch player able to say now sewing: Fill 1, and what
lets a tool highlight one object’s stitches. objectID matches an object id
in document.json when that entry is present; when it is not, the ranges still
partition the plan usefully on their own.
Summary values, all derivable from the arrays above — provided so a reader can show a file’s size and extent without walking it.
| Field | Meaning |
|---|---|
stitchCount | Number of sewn stitches. |
jumpCount | Number of jumps. |
trimCount | Number of trim commands. |
colorChangeCount | Number of colour-change commands. |
bounds | Design extent in millimetres. |
Derived and write-only
Section titled “Derived and write-only”plan.json reflects document.json at the moment it was saved. It is
output, and this is normative:
- Editors MUST NOT import
plan.jsonback into editable state. Doing so would replace a design with its own shadow — a stitch soup that cannot be re-digitised. - Re-writers MAY drop it, and SHOULD regenerate rather than copy it if the document changed.
- If
plan.jsonanddocument.jsondisagree,document.jsonis right and the plan is stale.
Tools that only consume — exporters, viewers, estimators, stitch players — are free to use it as their only input. The restriction is on writing back, not on reading.
A minimal exporter
Section titled “A minimal exporter”The complete job of a Level-0 reader:
- Open the
.hoopas a ZIP; verify entry CRCs and the manifest’s SHA-256 digests (Reader requirements). - Inflate
plan.json; parse it. - Walk
stitches, applying anycommandswhosebeforeStitchIndexequals the current index before emitting the stitch. - Convert millimetres to your target’s units and flip the y sign if it points down.
- Map
colorTableto whatever colour representation the target format has.
Nothing in document.json is required for this, and nothing in it will change
the result.