Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
A direct command skips the review prompt. Inspect the source before running it.
Single-parameter mode is compact by default (path, parameter, value, mode, label, mode-specific refs, menuNames); details=True restores default/style/range/menuLabels/menuIndex. Search ignores details
DAT Content
Tool
Parameters
Description
get_dat_content
op_path, format?
Get DAT text or table data ("text", "table", "auto")
set_dat_content
op_path, text?, rows?, clear?, confirm_wipe?
Full-replace DAT content. Refuses no-action calls and wipes (text="", rows=[], or clear=True with no content) unless confirm_wipe=True. For partial text edits prefer edit_dat_content; use this for tables, full rewrites, or intentional wipes.
Surgical text edit on a text DAT. old_string must appear exactly once by default; widen with context or pass replace_all=True. Refuses empty/identical strings and wipes unless confirm_wipe=True; not-found errors include diagnostics. Tables go through set_dat_content(rows=...).
Compact layout for all children in a COMP: path/type/nodeX/nodeY/nodeWidth/nodeHeight plus bounding_box; docked ops carry dockedTo (host name). Centers are nodeX+nodeWidth/2; annotation text is capped at 160 chars. Use instead of repeated get_op_position calls
Set position, size, color ([r,g,b] 0-1), or comment. Moving a host re-hugs its docked companions below the new spot (docks_moved); position the host before any explicitly-placed dock
Execute Python in TD. Set result variable to return values
Introspection & Diagnostics
Tool
Parameters
Description
get_td_info
(none)
TD version, build, OS, Envoy version
get_op_errors
op_path, recurse?
Get error and warning messages for op and children
exec_op_method
op_path, method, args?, kwargs?
Call a method on an operator
get_td_classes
(none)
List all Python classes in td module
get_td_class_details
class_name
Get methods, properties, docs for a TD class
get_module_help
module_name
Python help text for a module
get_docs
query, section?, source?, max_chars?
Look up official TD docs; offline mirror preferred, docs.derivative.ca fallback; normal responses return title, source, sections_available, content; ambiguous offline lookups return matches instead of a page
get_guidance
topic?
Read THIS project's checked-in TouchDesigner doctrine (.claude/rules/*.md, .claude/skills/*/SKILL.md). Bare call lists topics; topic returns one document. Matching ignores case/punctuation. Answered worker-side (no TD round-trip). Complements get_docs: get_docs is official Derivative documentation, get_guidance is how this project wants the work done -- and it is the ONLY way non-Claude-Code clients (Codex, Cursor, opencode) see these rules
get_focus
(none)
What the user is looking at: network (current pane), selected, current, rollover, plus target/targetSource and a note. Call it to resolve "this operator" / "fix this" before guessing a path. DISAMBIGUATION: "this" means the SELECTED/current op, NEVER the rollover (rollover is incidental mouse position). Headless TD returns headless: true with nulls
get_sessions
(none)
List AI client sessions connected to this Envoy (sid, label, pid, idle, last tool, recent_scopes = op paths/files recently modified, claims = scopes held, stale flag) plus you = caller's own sid. Check at session start and before large or destructive operations so concurrent sessions don't clobber each other. Response may include worktrees: in-flight durable worktree tasks, visible even after their session ended
claim_scope
scope, note?, ttl?
Cooperative WRITE lease on an op-path prefix, file:<repo-relative> path, or project:<name> scope. Peers' overlapping claims are refused while yours is live; their destructive ops on it are gated. Auto-renews on your own writes; expires on TTL or session silence. project:worktree-* claims are DURABLE: they survive session death and Envoy restarts, expiring when the worktree directory is removed (7-day backstop)
release_scope
scope
Release a lease you hold (polite; expiry also handles it)
announce_task
title, scopes?, note?
Announce a unit of work to the shared task ledger (.embody/tasks.json) so parallel sessions see what is being worked on and what is FINISHED but uncommitted. Announce at the start of substantive work (a feature, fix, refactor); keep it honest with update_task. Active entries ride on get_sessions for every session
update_task
task_id, status?, note?, commit?
Transition a ledger task: done_uncommitted when the work is finished but sitting uncommitted in the tree (the state peers MUST see), committed with the sha once it lands (a sha alone implies the transition), abandoned when dropped. Any session may update any task -- non-owner writes record updated_by
${ROWS}
preflight_landing
worktree_path
Landing safety check for a worktree diff -- intersects the files it would land with main-tree dirt, peer file: claims/touches, and unsaved live TDN state (tsv dirty column). Run BEFORE porting any worktree diff; verdict conflicts means reconcile first
MCP Prompts
Prompt
Parameters
Description
search_op
op_name, op_type?
Guide for searching operators
check_op_errors
op_path
Guide for inspecting/resolving errors and warnings
connect_ops
(none)
Guide for wiring operators
create_extension_guide
(none)
Guide for creating extensions
Embody Integration
Tool
Parameters
Description
externalize_op
op_path, tag_type?
Tag and externalize operator to disk (one step)
remove_externalization_tag
op_path, delete_file?
Remove externalization tracking (tag + row + TDN breadcrumb); delete_file=True also deletes the file (best-effort). Returns removed_tags, removed_rows, removed_anything, summary -- an operator can have a tracked row but NO tag, so check removed_anything, not removed_tags, to confirm cleanup
Preferred for reading ≥3 operators. Returns live network as a TDN dict. ~20-90x fewer tokens than get_op+query_network walks thanks to default-omission, type_defaults, and par_templates.
Write .tdn to disk. With output_file set, returns a compact summary (op/annotation counts + file path), NOT the full document -- Read the file for details. Without output_file, returns the full dict like read_tdn.
import_network
target_path, tdn, clear_first?
Recreate network from a parsed TDN document (on-disk .tdn is YAML in v2.0; reads legacy JSON)
diff_tdn
target?, max_changed_ops?, max_bytes?
What's UNSAVED in TDN networks (live vs on-disk .tdn) -- the view git can't give. Omit target -> whole project (every live TDN COMP, summarized); target = a COMP path OR a .tdn file path/bare filename -> that one COMP in full detail (old=disk, new=live). For committed/history diffs use plain git diff (Embody's .tdn diff driver keeps those clean). Read-only.
When to prefer read_tdn: exploring or auditing ≥3 operators, checking structure and parameters-as-authored, mapping connections, reading annotations. Scope cost with comp_path; cap with max_depth on large roots.
When NOT to use read_tdn: evaluated-expression runtime values (get_parameter), cook errors (get_op_errors), DAT/CHOP/TOP output data (get_dat_content, capture_top), cook timing (get_op_performance), flag state after runtime mutation (get_op_flags). read_tdn is an authored-state snapshot, not a runtime probe.
When to use diff_tdn: whenever the user asks "what's changed / unsaved?" for TDN networks. It shows what is UNSAVED -- the live in-memory network vs the on-disk .tdn -- which git cannot see (git only reads disk, never TD's live state). Omit target (or pass ""/"project") for a whole-project summary (every live TDN COMP: which changed + counts); pass a target (a COMP path OR a .tdn file path/bare filename, resolved to its COMP) for one COMP in full detail (old=disk, new=live). For committed/history diffs use plain git diff -- Embody installs a .tdn git diff driver so those are clean (the volatile export header is stripped). Read-only, non-interactive. Requires TD running.
Capture a TOP output. Returns a temp file path by default; inline=True embeds a small preview. sample_grid>=2 returns numeric NxN RGBA cells + channel stats instead of an image, clamped 2..32 with origin at top-left. The returned text carries a Quality verdict from the raw pixels (luminance + alpha stats): a Quality: FAIL flags a black / flat / fully-transparent frame so you can tell an empty render from a real one WITHOUT reading the image. Never declare a visual task done on a FAIL.
For visual work, success is verified by capturing and judging the output TOP, not by a clean network alone; see /visual-aesthetics.
Logging
Tool
Parameters
Description
get_logs
level?, count?, since_id?, source?
Get recent log entries from ring buffer
Auto-piggybacked logs: A _logs field rides along only when a WARNING or ERROR was logged during the call (capped at ~8) -- routine INFO/DEBUG/SUCCESS history is omitted to keep responses token-lean. Warning cursors are per session (from the bridge's identity headers), so concurrent sessions each receive their own copy of a warning -- one session polling first no longer consumes it for the others.
Auto-piggybacked peer advisories: a _peers field rides along when your request touches territory another session modified recently (last ~10 min) -- one entry per peer: {label, scope, tool, age_s, conflict}. conflict: true means a peer WROTE an overlapping scope within the last minute AND your operation is also a write -- treat it as a hard stop: check get_sessions, coordinate (or divide work by COMP subtree), and only then proceed. Non-conflict advisories are informational and deduped per (peer, scope) for ~5 min; conflicts always ride.
Destructive-op gate: delete_op, import_network with clear_first=True, run_tests, and batches containing them are REFUSED (MULTI-SESSION GATE error naming the holder/peer) while a live peer session claims the scope or wrote it within the last minute. Pass override=True only when certain, and say so. Call get_logs for the full history, or read the log files in Embody's logs directory (see the Logfolder parameter on the Embody COMP).
Auto-attached recovery hints: when a tool returns an error, a recovery_hints list may ride along -- each entry is {cause, action, next_tools} keyed off the error message (path-not-found, wrong family, empty capture, thread conflict, timeout, ...). It tells you the likely cause and which tool to call next, so recover by following it rather than retrying the same failing call verbatim.
Testing
Tool
Parameters
Description
run_tests
suite_name?, test_name?, override?, background?
Run Embody unit-test suites (all, one suite, or one test; 300s timeout). Destructive and agent tiers are excluded -- they run only via their dedicated entry points. Gated by the multi-session destructive-op gate; override bypasses it (say so when you do). background=True (recommended for full runs) returns a job id immediately -- poll get_job_status; the synchronous mode is severed by the watchdog suites' server restart
get_job_status
job_id?
Status of background jobs (run_tests background=True, save_project). Disk-backed (.embody/jobs/), so results survive server restarts and extension reinits; omit job_id to list recent jobs. Finished run_tests jobs carry the summary + failing tests
save_project
(none)
Save the project as a tracked job: returns a job id immediately, the save runs a few frames later (a synchronous call is severed by the save's own main-thread block + extension reinit). Finished record carries version_before/version_after
Bridge Meta-Tools
These run locally on the STDIO bridge — they work even when TD is not running.
Tool
Parameters
Description
get_td_status
(none)
Check if TD is running, Envoy reachable, crash detection, process liveness. Includes instance registry and live bridge sessions (from heartbeat files -- works even with TD down)
launch_td
timeout?
Launch TD with the project's .toe file, wait for Envoy (default: 120s)
restart_td
timeout?
Gracefully quit TD and relaunch, wait for Envoy (default: 120s)
switch_instance
instance?, all_sessions?
List all registered TD instances (omit instance) or re-pin THIS session's bridge to a different running instance (provide toe basename without .toe); peers are untouched unless all_sessions=true (writes the registry default and bumps active_epoch, moving every session). See /multi-instance skill for workflow
Convoy Tools (LAN work relay)
Sixteen additional meta-tools drive Convoy, relaying work to Convoy-enabled Embody nodes on the trusted LAN through the local per-user host app. Status and inventory calls (get_convoy_status, convoy_list_nodes, convoy_list_controllers, convoy_ping) never wake TouchDesigner.
convoy_select_node pins THIS session to one exact node -- ordinary Envoy tools then run there until convoy_select_node with clear=true.
convoy_call / convoy_batch run registered operations on explicit one-off targets; pass a unique idempotency_key per intended action so a retry reconciles instead of double-running.
convoy_get_job / convoy_ack_job / convoy_cancel_job reconcile durable deliveries; acknowledge a finished delivery you have safely observed so the target can release its protected result artifacts.
convoy_forget_node deletes a stale node row on THIS machine's host app (a renamed, moved, or deleted project's leftover). It refuses only while the node has a delivery that has not FINISHED, and names the blocking delivery ids in its refusal (a finished-but-unacknowledged result never holds a row -- results are fetched by delivery id and outlive it); dead and long-unseen rows are also evicted automatically by the host's retention sweep.
convoy_get_artifact / convoy_save_artifact fetch results BY ARTIFACT REFERENCE and verify them locally -- never open a remote C:\... or /Users/... path as if it were local.
convoy_start_node / convoy_restart_node manage node lifecycle; restarts require the node's CURRENT runtime id (from convoy_list_nodes) plus a unique idempotency_key, and the default policy refuses dirty or unverifiable project state.
convoy_owlette is an optional read-mostly site bridge that fails closed without credentials.
Batch Operations
Tool
Parameters
Description
batch_operations
operations
Execute multiple operations in a single request. Reduces latency and token overhead
operations is a list of {"tool": str, "params": dict} objects. Each entry maps to an existing tool name and its parameters. Stops on first error.
When to use: 3+ calls to the same tool type (positioning, connecting, parameter setting, flags). Use execute_python instead when you need conditionals, loops, or computed values between operations.
Example — position 4 operators + connect them in one call: