Skip to main content

multi-instance

Workflow for running multiple TD instances with Envoy, switching between them, and understanding the instance registry.

소스 정보

저장소
dylanroscover/Embody
최근 소스 활동
2026년 10월 7일 08:19
감지된 SKILL.md 언어
영어
스타
191
포크
10

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
multi-instance
description
Workflow for running multiple TD instances with Envoy, switching between them, and understanding the instance registry.
# Multi-Instance Workflow Envoy supports multiple TouchDesigner instances running simultaneously in the same git repo. Each instance gets its own port, and the bridge can switch between them on demand. ## Architecture ``` Claude Code <--> STDIO Bridge <--> Envoy (TD instance A, port 9870) | +---switch---> Envoy (TD instance B, port 9871) ``` - **One bridge process per SESSION** (spawned by each AI client's MCP client) - **Per-session pinning** - each bridge pins to an instance NAME and re-resolves its port from the registry every tick, so a pinned instance restarting on a new port still self-heals, and a save that renames its `.toe` is followed (same TD process). The registry `active` field only seeds NEW bridges without a pin. - **A vanished pin fails closed** - if the pinned instance leaves the registry (closed, crashed), the session has no target: calls return `envoy.instance.unavailable` and nothing is forwarded - never to another instance - until it re-registers (a call that names another instance with `instance=` still goes there). Recover with `launch_td` (reopens the pinned `.toe`) or `switch_instance`. - **Per-call addressing** - every Envoy tool accepts an optional `instance` argument; the bridge routes that one call to the named instance and leaves the pin alone (unknown or unreachable names fail only that call with `error_code` `envoy.instance.unknown` / `envoy.instance.unreachable`). Prefer it over switching when you only need one look at another instance. - **Switching is instant and session-local** - `switch_instance` re-pins THIS session's bridge in-memory; peers are untouched unless you pass `all_sessions=True` (writes the registry default and bumps `active_epoch`, which moves every session) - **Registration never re-routes running sessions** - a new instance takes the `active` default slot only when it is vacant or names a dead instance ## Instance Registry (`.embody/envoy.json`) Each Envoy instance registers itself in `.embody/envoy.json` at the git root on startup: ```json { "active": "Embody-5.257", "td_executable": "/Applications/TouchDesigner.app", "instances": { "Embody-5.257": { "toe_path": "dev/Embody-5.257.toe", "port": 9870, "td_pid": 12345 }, "MySecondProject": { "toe_path": "MySecondProject.toe", "port": 9871, "td_pid": 67890 } } } ``` | Field | Purpose | |-------|---------| | `active` | Default instance for NEWLY-spawned bridges (each bridge then pins per-session; only an `active_epoch` bump re-targets pinned bridges) | | `td_executable` | Path to TD app (used by `launch_td`) | | `instances.<name>.toe_path` | Relative path to the `.toe` file | | `instances.<name>.port` | Envoy HTTP port for this instance | | `instances.<name>.td_pid` | OS process ID of the TD process | Instances are added on Envoy startup and removed on graceful shutdown (`onDestroyTD`). ## Port Allocation Each instance picks a port from a 10-port range starting at the configured `Envoyport` parameter (default: `9870`): 1. Try the base port first 2. If occupied by **this** TD process's old server, force-close it and reclaim 3. If occupied by **another** process, scan `base+1` through `base+9` 4. First available port wins; if all 10 are taken, startup fails This means up to 10 simultaneous instances per base port. ## Workflow: Running Multiple Instances ### 1. Open the first `.toe` file Launch TD normally or via `launch_td`. Envoy starts on its configured port and registers in `.embody/envoy.json`. ### 2. Open additional `.toe` files Open them in separate TD instances (File > Open or double-click). Each Embody/Envoy auto-starts and claims the next available port. ### 3. List instances Call `switch_instance` with no parameters to see all registered instances and their status: ``` switch_instance() ``` Returns each instance's name, port, PID, reachability (PID alive + port responding), and whether it's the active target. ### 4. Switch to a different instance ``` switch_instance(instance="MySecondProject") ``` The bridge immediately redirects to the target instance's port. All subsequent MCP calls go to that TD process. ### 5. Switch back ``` switch_instance(instance="Embody-5.257") ``` ## Reachability Checks An instance is **reachable** only when: - Its registered PID is alive (`kill -0` / process table check) - Its registered port responds to a TCP connect Both conditions must be true. A dead PID with an open port means another instance reused that port - the entry is stale. `get_td_status` includes the full instance registry with reachability in its response. ## Stale Instance Cleanup Instances are deregistered on graceful TD shutdown. If TD crashes: - The PID becomes dead, so the instance shows as unreachable - The port may be freed, allowing a new instance to claim it - Stale entries remain in `.embody/envoy.json` but are filtered by reachability checks - Re-launching TD with the same `.toe` overwrites the stale entry ## Closing Instances **Preferred**: Close TD instances via Envoy by calling `execute_python` with `project.quit()`. This prompts the user to save unsaved changes, then triggers `onDestroyTD` for clean deregistration and port release. Works reliably across platforms. To close a specific instance, `switch_instance` to it first, then send the quit command: ```python switch_instance(instance="MySecondProject") # target the instance execute_python(code="project.quit()") # user gets save prompt in TD ``` **Never use `project.quit(force=True)`** unless the user has explicitly asked - it skips the save dialog and risks losing unsaved work. **Avoid**: `osascript -e 'quit app "TouchDesigner"'` and similar OS-level approaches are unreliable - they may not target the correct instance and don't guarantee clean Envoy shutdown. ## Common Scenarios | Scenario | Action | |----------|--------| | Test code in two `.toe` files side by side | Open both, `switch_instance` between them | | Test code in a secondary `.toe` | Open it, switch to it, perform work, switch back | | Check if a second TD is still running | `switch_instance()` (list mode) or `get_td_status` | | One instance crashed, want the other | `switch_instance` to the surviving instance | | Close a specific instance | `switch_instance` to it, then `execute_python` with `project.quit()` | ## Same-Project Instances When you open the same `.toe` file in multiple TD instances, Envoy auto-suffixes the registry key to avoid collisions. The first instance registers as `MyProject`, the second as `MyProject-2`, etc. Stale entries (dead PIDs) are automatically reclaimed. ## Limitations - The bridge connects to **one instance at a time** - no parallel MCP calls to multiple instances - Maximum **10 instances** per base port range - `.embody/envoy.json` is per git root - instances in different repos have separate registries - `launch_td` and `restart_td` act on this session's pinned instance and its `.toe` (unpinned: the registry default) - pass `project_path` to open another file - Opening the same `.toe` file in multiple instances auto-suffixes keys (`MyProject-2`, `-3`, etc.)
GitHub에서 보기