binary .toe / .tox
- Opaque — requires TouchDesigner to inspect
- Binary diff — "file changed"
- Invisible to AI agents
- Revert = restore entire binary file
- Merge conflicts are unresolvable
- Fixed size regardless of complexity
TDN / TOUCHDESIGNER NETWORK FORMAT
TDN exports any TouchDesigner network as clean, human-readable JSON — only the parameters you actually changed, structured so any tool can understand it. Your AI agent can read it. Your team can review it. Git can diff it line by line.
THE CONTRAST
TDN gives your TouchDesigner networks a second representation — one designed for diffing, reviewing, and reading. A format where every change is visible, every version is comparable, and every operator is text your tools can work with.
.toe / .tox.tdngit checkout a specific changeCOMPLETE REPRESENTATION
TDN captures the complete state of a network. Everything that defines the network is in the file; everything that doesn't is left out.
Name, type, position, size, color, comment, tags — the full identity of every node.
Only non-default values. Constants, expressions (=), and binds (~) — nothing else.
Input wiring as arrays. Position equals input index. No wrappers, no ceremony.
Complete definitions — pages, styles, ranges, menus, defaults, help text. Ready to rebuild.
Viewer, display, render, bypass, lock, expose — compact arrays with - prefix for negation.
Text and table data embedded directly in the JSON. Scripts, lookup tables, configuration — all in one file.
Dicts, lists, tuples, sets, and bytes. Python types round-tripped with $type wrappers.
Annotate, comment, and network box modes — position, size, color, opacity. Your documentation, preserved.
Recursive children, COMP inputs, docking relationships, and tdn_ref pointers for independently externalized COMPs.
Clone relationships preserved. Children excluded — TD recreates them from the clone source automatically.
Resizable parameter blocks — GLSL uniforms, Combine blocks, channel constants — round-tripped with portable base names.
FORMAT DESIGN
Every design decision serves a single goal: the smallest possible output that remains fully readable. A network with 50 operators where you only changed a few parameters produces a file measured in kilobytes, not megabytes.
// expression — just prefix with =
"period": "=absTime.frame * 0.1"
// bind — just prefix with ~
"tx": "~op('ctrl').par.x"
// negated flag — just prefix with -
"flags": ["viewer", "-expose"]
// connections — position = input index
"inputs": ["noise1", null, "level1"]
// constant — no wrapper needed
"amp": 0.8
par_templates and referenced via $t. Definitions stored once, values per-operator.= for expressions, ~ for binds, - for negated flags.["noise1"] instead of [{"index": 0, "source": "noise1"}]. Array position equals input index.Round-trip safe. Export a network, edit the JSON, import it back. Same network. Every time.
RELIABILITY
TDN is the source of truth for externalized networks. Every write must be bulletproof.
Every save writes to a temp file first, calls fsync, then uses os.replace to swap it in. No partial writes. Ever.
A .tdn_backup/ directory keeps two generations of previous versions. Recover from any bad export instantly.
After every write, the file is read back and JSON-parsed to confirm integrity. If validation fails, the backup is restored automatically.
If the new export matches the existing file, the write is skipped entirely — preserving git timestamps and avoiding noise commits.
The importer runs 8 ordered phases. A single failed operator never aborts the entire import — partial results are more useful than total failure.
VERSION DURABILITY
Some TouchDesigner operators reset certain parameters during initialization — a camera's tz is reported as 0 by default, but TD actually creates it at 5. A non-default comparison that trusts the reported value will silently omit your intended setting. TDN catches this.
The first time you open a project on a new TD build, Embody scans every creatable operator type in the background, samples the actual creation values, and writes a per-build catalog. TDN exports compare against those real values instead of the reported defaults. When you upgrade TD, the catalog detects which creation values shifted between builds and automatically patches your operators to preserve your intent. An elegant solution to a very obscure problem — but the kind that would otherwise cost you hours of debugging a parameter that "just changed" after an update.
Upgrade-proof. Export on one build, open on another. Every parameter value survives.
THE WORKFLOW
TDN is not a standalone format. It's the substrate that connects the other two layers of Embody — the format that makes both forward and lateral velocity possible.
forward velocity.
Your AI agent exports the current network as TDN to see what's on screen. It generates or modifies the JSON, then imports it back — changes appear instantly in your live session.
lateral velocity.
Tag a COMP, choose TDN as its externalization strategy, and every save writes the network to a .tdn file. On project open, children rebuild themselves from text automatically.
the record.
Commit the .tdn file. Every change is a clean diff. Review network modifications in pull requests. Branch off working versions. Revert broken experiments.
The substrate. Tag a COMP. Save it as TDN. Commit the file. Let your agent read it, modify it, import the result. All without touching a binary.
SPECIFICATION
.tdn
application/json
A REAL FILE
{
"format": "tdn",
"version": "1.3",
"generator": "Embody/5.0.351",
"td_build": "2025.33020",
"exported_at": "2026-04-10T08:15:00Z",
"network_path": "/project1",
"type": "containerCOMP",
"options": { "include_dat_content": true },
"operators": [
{
"name": "noise1",
"type": "noiseTOP",
"parameters": {
"amp": 0.8,
"period": "=absTime.frame * 0.1",
"harmons": 4
},
"flags": ["viewer"]
},
{
"name": "blur1",
"type": "blurTOP",
"parameters": { "size": 8 },
"inputs": ["noise1"],
"position": [400, 0]
},
{
"name": "level1",
"type": "levelTOP",
"parameters": {
"opacity": "~op('ctrl').par.Fade",
"brightness1": 1.2
},
"inputs": ["blur1"],
"flags": ["display", "render"],
"position": [800, 0]
}
],
"annotations": [
{
"name": "annot1",
"mode": "annotate",
"title": "noise pipeline",
"position": [-100, -200],
"size": [1100, 400]
}
]
}
Three operators, one annotation, one expression, one bind. Every required field present, every value spec-accurate — readable, diffable, importable.
DOCUMENTATION
The complete field reference — every property, every inclusion condition, every default value.
Machine-readable schema for validation and IDE auto-completion.
Complete, minimal, and annotated .tdn files you can study and use as templates.
Keyboard shortcuts, MCP tools, the 8-phase import process, and error handling.