---
name: create-extension
description: "MUST READ before calling create_extension. Required parameters, lifecycle methods, and wiring steps."
---
<!-- Generated by Embody/Envoy - Do not remove this comment -->

# Create Extension Workflow

Use the `create_extension` MCP tool to create a fully-wired TD extension:

```
create_extension(
    parent_path='/path/to/parent',
    class_name='MyFeatureExt',
    name='MyFeature',           # Optional: COMP name
    code='...',                 # Optional: initial Python code
    promote=True,               # Optional: promote extension methods
    ext_name='MyFeature',       # Optional: extension name
    ext_index=0                 # Optional: extension index
)
```

This creates: baseCOMP + text DAT + extension wiring, initialized and ready to use.

## Extension Lifecycle Methods

Always implement these in your extension class:

```python
class MyFeatureExt:
    def __init__(self, ownerComp):
        self.ownerComp = ownerComp

    def onDestroyTD(self):
        """Called on old instance before TD reinitializes. Clean up callbacks, timers, etc."""
        pass

    def onInitTD(self):
        """Called at end of frame after init. Safe to access other extensions and cooked network."""
        pass
```

## Naming Convention

Extension classes and source DATs must follow the `NameExt` convention:
- Class: `MyFeatureExt`
- DAT: `MyFeatureExt` (matches class name)

## Referencing Extensions

```python
# Promoted methods (uppercase) — called directly on the component:
op.MyFeature.DoSomething()

# Non-promoted methods (lowercase) — accessed through ext:
op.MyFeature.ext.MyFeature.helperMethod()
```

**NEVER cache extension references** in variables — always call inline. Cached refs go stale on reinit.

## Extensions Inside TDN COMPs

If the extension lives inside a TDN-strategy COMP (or the extension's ownerComp is one), `onInitTD` will fire **before** TDN import reconstructs the network. Any state set up during `onInitTD` — created operators, parameter values, stored data — is overwritten when `ImportNetwork` runs with `clear_first=True`.

**Always defer initialization:**

```python
def onInitTD(self):
    """Defer setup so it runs after TDN import completes."""
    run('args[0].postInit()', self, delayFrames=5)

def postInit(self):
    """Safe to set up state here — TDN import is complete."""
    # Create operators, set parameters, initialize state
    pass
```

This applies on project open, after every Ctrl+S (strip/restore cycle), and on manual TDN reimport. The deferred method must be idempotent — it may run multiple times.
