Editing a document from outside Field
You can edit a box's code in your own editor, or have a script or an agent write it, and Field picks up the change while the document is open. That works because a document is a folder on disk and each box's code is a plain file in it. This page covers which file to edit, what Field does when it changes, and the few cases where your edit does not take effect or is overwritten.
What a Document Is on Disk explains the format itself: every file a save writes, and which copy wins on load.
Find the file
A document called sketch in your workspace is the folder <workspace>/sketch/. Each box's
code is saved beside metadata.edn as its own file, named after the box's id:
sketch/
metadata.edn
f2b585c8-0009-44cd-8181-06ac28784e2d_code_.kt
7a2b3e64-f79b-4ef1-bd50-5eeb48d30886_code_.kt
7a2b3e64-f79b-4ef1-bd50-5eeb48d30886_fragment_.glsl
7a2b3e64-f79b-4ef1-bd50-5eeb48d30886_vertex_.glsl
backups/
The name is <box id>_<property>_.<extension>. It uses the box's uid, which stays the same when
you rename the box. To find a box's file, search for its code with
grep -l or look the id up in metadata.edn, where each box's "name" sits beside its "id".
These properties get their own file:
| Property | File extension |
|---|---|
code |
.kt |
fragment, vertex, compute, task, mesh and the ray-tracing stages |
.glsl |
vertex_fragment, fragment_s and the other _s stages |
.slang |
metadata |
.yaml |
customization |
.js |
Box.ioSeparateProperties in Boxes.kt holds the full list. The root box never gets these
files: its properties live in metadata.edn.
Edit a box's code
Save the file. Within about two seconds the box's code holds what you wrote. Field sends the new text to any
editor showing that box, a notification says Reloaded external change to code in ..., and Field's
next autosave updates the copy in metadata.edn.
Field reloads the code but does not run it. A box that is not running runs your version the
next time you run it. A box that is running carries on with the code it started with: a loop
printing tick v1 kept printing tick v1 after its file was changed to print tick v2.
Stop the box and launch it again to run the new version.
To have the box run each new version as soon as it is reloaded, set its onExternalEdit
property to run (the backdoor: set <box> onExternalEdit run). With it set, saving a file
that printed version 2 from disk reloaded the box and ran it, and version 2 from disk was
printed without touching Field. Leave the property unset to keep reloading without running.
Edit a shader
A .glsl file works the same way: the box's fragment (or vertex, ...) property is replaced,
and the shader on screen does not change. The renderer recompiles a shader only when you ask it
to, so after saving the file, select the box and use Reload Shader (alt r). Setting the box's onExternalEdit property
to reload-shader runs Reload Shader for you after each reloaded file.
Add a box by writing a file
A new file named for an id that is not in the document creates a box. Writing
from-script_code_.kt into an open document added a box with id from-script, put it in a free
spot on the canvas, gave it that code and saved the document. The box is named after its id.
This is the simplest way for a script to add a box: choose a readable id, write the file, and the
box appears.
When your edit loses
Field and your editor can disagree about a box. These cases decide which version is kept.
You edited the same box in Field and on disk. If you change a box in Field and then change
its file before Field has autosaved, the autosave writes Field's version over your file. The file
you wrote is not lost: Field backs up the previous contents of a file before overwriting it, so
your version is the newest <id>_code__backup_*.kt in backups/. Field also says so when it
happens: a notification names the file and a copy of your disk version,
backups/<id>_code_.kt.external-<time>, written the moment Field decided to keep its own edit.
To avoid this, edit a box in one place at a time, or wait a few seconds after typing in Field
before editing the file.
The document was not open. Field watches a document only while a Field window (or another
client) has it open. A file you change while the document is closed is not lost: it is read
when the document next opens, and that file wins over the copy in metadata.edn.
You deleted the file. Deleting a box's file does not delete its code. The box keeps the code it had, and the next save writes the file back. To delete a box, delete it in Field.
You edited the code inside metadata.edn. metadata.edn keeps a copy of each box's code
as "inline". Changing that inline text while the document is open applies it to the box, and the
next save writes it to the box's own file. When the document is closed, the newer of the two wins
on the next open: an inline edit saved after the box's file replaces it, and the file's text is
kept in backups/ as <id>_code_.kt.before-inline-<time>.
Edit metadata.edn itself
Everything else about a box (its name, frame, connections and other properties) lives in
metadata.edn, and Field applies hand edits to it while the document is open. In a test, changing
a box's "name" and "frame" renamed and moved it on the canvas, and adding a new
{"id" ... "properties" {...}} entry to the "boxes" list created the box. Adding or removing a box's id in
another box's "children" (or "parents") connects or disconnects them. Deleting metadata.edn
while the document is open does not delete the document: Field says so and writes the file back on
its next save. What a Document Is on Disk
gives the exact rules.
Field also writes a document.md beside metadata.edn: a readable copy of the boxes and their
code, meant for tools that read documents. Field never reads it, so editing it changes nothing.
How this page was checked
Every behaviour above was run on 2026-10-18 against a live Field on a scratch document,
editing files from a shell while the backdoor held the document open, and checking the box
with the backdoor's boxes, run, wait-output and native-screenshot commands and
~/.afield/logs/save_reload.log. The page has no figures because a docs-runner capture fence
cannot interleave a shell and a running Field over several seconds.
Three of them are pinned by tests: a second edit to a file before Field's autosave
(examples.file-watch.sidecar-reedit), an edit to the inline code in metadata.edn
(FileWatchMetadataReconcileTest.anEditToAnInlineSidecarCopyIsApplied), and a disk edit
overridden by an unsaved Field edit (anExternalEditOverriddenByAnUnsavedFieldEditIsKept).
Those last two, and onExternalEdit, were checked on 2026-10-19.