td-atlas RU·EN Try it

TouchDesigner via td-atlas

Перевод английской документации от 29.09·English

TouchDesigner is a node-based visual programming environment. td-atlas gives you an offline index of the installed build (operators, parameters, documentation, palette) plus a live bridge into a running instance.

The one thing that will waste your time

TouchDesigner reports almost nothing when work silently does nothing. A network that never cooks raises no error. Nor does a flag left off, an output device switched off, a CPU-bound operator holding the frame rate down, or a resolution silently halved by the licence. Three separate hours have been lost to exactly this.

Run td_health after building anything, and whenever something "looks fine but does nothing". It is the tool that catches these. When it says nothing is cooking, td_flags says which flag is the reason. The keys are the ones TouchDesigner uses, so cooking is allowCooking, not cooking; the full set is display, render, bypass, lock, expose, viewer, activeViewer, cloneImmune, allowCooking, selected, pickable. td_set_flags reads every write back, so a flag a family will not take comes back as a refusal, and so does a name that is not one of these.

Two more questions have their own tool. Why is the output black, or darker than its parameters say: td_trace walks up the TOP's inputs and marks the node where the image was lost, went below zero or turned NaN. Who spends the frame when the frame rate drops: td_timeline_profile times each operator on real timeline frames with the GPU waited for.

Order of work

  1. Search the index first. It is offline and free, with no round trip to TouchDesigner. Never guess a parameter name. The index is not there until td-atlas build has run once; references/tools.md has that command and the rest of the setup.
  2. Read the schema of any operator before creating it.
  3. Build with td_build, not a series of single calls.
  4. Look at the result with td_render, and at motion with a contact sheet.
  5. Run td_health.

Working from a reference video or image, measure the reference before you choose how to build it — the motion from consecutive frames (a dozen, a few apart; frames a second apart do not show motion), the shape from a few numbers you can take from your own output the same way. In three agent sessions the model chosen from memory cost more rounds than anything this index lacked, and what turned each one was a number taken from the reference.

td_log(failures=True) is your own trail, every bridge call this host made, with the text each refusal came back with. Reach for it when a call refuses and you do not know why, or when the artist says something broke while you were working. td_log(summary=True) says which method has been failing repeatedly, which is the signal that the approach is wrong. It outlives the TouchDesigner session, so it also answers "what happened yesterday". A call that changed the project carries what it changed: tx = 0.5 (was 0.2), each step of a batch, the first lines of a td_exec's code. A secret in it, found by pattern, reads [redacted].

Finding the right operator

Ask for what the operator does, in plain language, with td_search_operators("displace an image with noise").

Two things it cannot do, and the way round each:

td_glossary("cook") defines the vocabulary the documentation assumes.

Parameter names

td_operator_schema("noiseTOP") always gives exact names. Defaults, menu options and ranges appear once td-atlas probe has run against a live TouchDesigner; without that run the schema says so itself, in place of the values. Two traps:

A sequence (a Constant CHOP's channels, a GLSL TOP's arrays and uniforms) shows its first block in the schema: const0name, array0name. Later blocks are written the same way with the next number — const1name, array3type — and td_build adds the blocks they need. To set the count outright, give the sequence's own parameter a number: "const": 4. Setting it by hand in TouchDesigner (par.const = 4) does nothing; seq.const.numBlocks = 4 does.

td_build validates parameter names against the index before sending anything, resolving each target's type itself, so a mistake comes back as t: is a parameter group, not a settable parameter (try: tx, ty, tz). The check is a convenience, not a guarantee: with no index built, and for an existing node whose type the bridge cannot report, the batch goes out unchecked. td_set_params does the same, asking the bridge for the node's type when you do not pass op_type.

Building

Use td_build for anything multi-step:

json
[
  {"method": "op_create", "params": {
     "parent": "/project1", "type": "noiseTOP", "name": "n1",
     "position": [-600, 0],
     "pars": {"type": "simplex3d", "period": 3.5,
              "tx": {"expr": "absTime.seconds * 0.1"}}}},
  {"method": "op_create", "params": {
     "parent": "/project1", "type": "blurTOP", "name": "b1",
     "pars": {"size": 6},
     "connect": [{"from": "/project1/n1", "index": 0}]}}
]

The whole batch lands in one ui.undo block. If any step fails everything rolls back, and a successful batch is a single Ctrl+Z for the person using TouchDesigner. Parameter values may be a constant, {"expr": "..."} for an expression, {"bind": "..."}, or {"pulse": true}.

A DAT's contents are not a parameter, so they go in their own text key on op_create. That covers shader source, script bodies and callbacks. Doing it there puts the text in the same rollback and the same Ctrl+Z, and saves a follow-up td_exec:

json
{"method": "op_create", "params": {
   "parent": "/project1", "type": "textDAT", "name": "frag",
   "text": "out vec4 fragColor;\nvoid main() { fragColor = vec4(1.0); }"}}

A DAT whose text is an output (Select, Null, Info, the script generators) is refused, since it would overwrite the assignment on its next cook.

This was measured live on 2026-08-30, against build 2025.32460. A fragment shader delivered this way to a textDAT, with a glslTOP created in the next step pointing its pixeldat at it, compiled. compileResult read Compiled Successfully, and the TOP's first pixel came back as the colour the shader writes. A shader that does not compile is a warning, not an error, and compileResult is where the line number lives, which td_health reads for you.

The methods are op_create, op_delete, op_connect, op_disconnect and par_set. undo is not one of them, since it walks the history the batch is being recorded into. Call td_undo on its own, after.

If another agent or session may be in the same project, claim your subtree with td_claim_scope(path, owner) first. Then pass that same owner into every tool that writes: td_build, td_set_params, td_set_flags, td_annotate, td_palette_load and td_extension_add, or your own claim refuses your own writes. td_release_scope hands it back, and td_scopes says what is already held.

td_annotate leaves the reason for what you built beside the nodes, as a box the artist can read. td_annotations reads notes back, including a brief a person left for you, which no other tool here shows.

Seeing what you made

td_render("/project1/b1") returns the image. Use it, since inferring appearance from parameter values does not work. save_to writes the PNG to a path instead, and a file already there is refused unless overwrite=True. Right after an edit pass settle_frames=2 or 3, or the render can be the frame from before it.

For a strobe or any other simple animation, a single frame is a coin toss. Use a contact sheet:

python
from td_atlas.bridge.client import BridgeClient
from td_atlas.bridge.filmstrip import contact_sheet
contact_sheet(BridgeClient.discover(), "/project1/b1", "sheet.png",
              frames=9, interval=0.13, columns=3)

A contact sheet samples wall-clock time. When a frame depends on the ones before it, as with a Feedback TOP, a trail or live audio, use td_timeline_run instead: it walks the timeline frame by frame and saves the frames you pick.

Reading projects from disk

None of this needs TouchDesigner running, and td_project_read gives the tree. td_project_text gives the whole network as JSON, every parameter, wire, flag and DAT line. td_project_grep reaches the Python and GLSL inside DATs, which no file search can, since that code lives inside the .toe container. A network too big for one result is refused, and never truncated. Narrow it with path, or write it out with td-atlas project text FILE -o network.json.

td_project_write is the return leg, an edited dump into a new file. It is a patcher, so it needs the original file too, and it lists what it could not write, so read those gaps before assuming.

Before trying a direction, td_variant_save(file, label) keeps the current state, and td_variant_list/_restore/_diff branch, restore and compare.

On a live instance, to keep a branch's parameters before changing them, do not dump them to text by hand:

  1. td_snapshot("before", path="/project1/branch") writes that COMP to a .tox and replies with the file path.
  2. Make the edits.
  3. td_snapshot("after", path="/project1/branch"). The label must differ, because a reused label replaces the file you meant to compare against.
  4. td_project_diff(before=<before.tox>, after=<after.tox>) lists each changed parameter as name: old -> new, expressions and custom parameters included.
  5. To roll back, use td_undo while the edits are still on its stack. Otherwise take the old values from td_project_text(<before.tox>) into td_set_params. The diff shows an expression's text without saying it is one, and the text keeps it as {"expr": ...}. Paths in a snapshot start at the COMP's own name, so /branch/blur1 in the file is /project1/branch/blur1 live. Put the COMP's parent path in front.

Never save the artist's project. project.save() is Save As in disguise and moves the file they have open. Nothing here needs it; TouchDesigner writes the network text beside the .toe when they save.

Things that will bite you

Detail in references/gotchas.md, and the short list follows:

Command line

bash
td-atlas status                     # install, index and bridge state
td-atlas doctor                     # every link, with the command that fixes it
td-atlas search "blur an image"
td-atlas op noiseTOP --page Noise
td-atlas render /project1/n1 -o out.png
td-atlas project diff a.toe b.toe
td-atlas project variant save a.toe --label try1   # branch, restore, compare
td-atlas log --failures             # the same trail as td_log
td-atlas reload                     # upgrade the bridge in place

If the bridge is unreachable

td-atlas install prints a one-line bootstrap to paste into TouchDesigner's textport. The textport opens from the menu, Dialogs → Textport and DATs. Do not reach for the keyboard shortcut. A blind key combination lands in the network editor when the window is not focused, and creates operators in the artist's project. Re-running the bootstrap upgrades in place. td_instances says which running TouchDesigner these tools actually reach. Check it before believing an edit landed in the project you meant.