Extension System in Modly: Key Files and Architecture Explained

The extension system in Modly relies on five core TypeScript modules—electron.d.ts, extensionsStore.ts, preflight.ts, workflowRunStore.ts, and ExtensionNode.tsx—that coordinate IPC contracts, state management, workflow validation, runtime execution, and UI rendering to enable GitHub-hosted model and process extensions.

The lightningpixel/modly repository implements a plugin architecture that allows developers to extend the application by dropping GitHub-hosted repositories into the app. Understanding the extension system in Modly requires familiarity with a specific set of TypeScript files that bridge the Electron main process, React renderer, and Python runtime. These modules handle everything from manifest.json validation to process execution, creating a clean separation between declaration, state, and runtime concerns.

IPC Contract Definitions

src/shared/types/electron.d.ts

This file defines the TypeScript interface for the Electron IPC bridge that enables communication between the renderer (React) and main processes. It declares the methods available on window.electron.extensions, including list, installFromGitHub, installFromLocal, uninstall, reload, and runProcess.

When the UI needs to interact with the extension system, it calls these typed methods. The main process implements the underlying logic that reads the extension folder, validates the manifest.json structure, and launches Python processes for model or process extensions.

State Management Layer

src/shared/stores/extensionsStore.ts

The central Zustand store that caches loaded extensions and provides actions for installing, uninstalling, and reloading them. This file tracks install progress and errors through window.electron.extensions.onInstallProgress.

The store maintains two critical arrays—modelExtensions and processExtensions—that populate the UI throughout the application. When you invoke loadExtensions(), the store calls the Electron IPC methods defined in electron.d.ts and updates the cached state with the validated extension list.

import { useExtensionsStore } from '@shared/stores/extensionsStore'

function InstalledExtensions() {
  const { modelExtensions, processExtensions, loadExtensions } = useExtensionsStore()
  React.useEffect(() => { loadExtensions() }, [])
  return (
    <div>
      <h3>Models</h3>
      {modelExtensions.map(e => <div key={e.id}>{e.name}</div>)}
      <h3>Processes</h3>
      {processExtensions.map(e => <div key={e.id}>{e.name}</div>)}
    </div>
  )
}

Workflow Integration Components

src/areas/workflows/preflight.ts

This module performs static validation of workflows before execution. It verifies that every extension node refers to a known extension and that required inputs/outputs are satisfied. The validator uses getWorkflowExtension, a helper that lookups extensions by ID in the store, to confirm node validity.

When validation fails, the system reports missing-extension issues that surface as UI warnings, preventing runtime errors from undefined extensions.

src/areas/workflows/workflowRunStore.ts

The runtime execution engine that steps through workflow nodes. When encountering a node of type extensionNode, it invokes window.electron.extensions.runProcess (or model-specific endpoints) to execute the extension's Python entry point.

This file relies on the extension's manifest.json to determine the command to run and maps inputs/outputs accordingly. It handles errors returned from the backend and bubbles them up to the UI with full stack traces.

// inside workflowRunStore.ts
if (node.type === 'extensionNode') {
  const ext = getWorkflowExtension(node.data.extensionId ?? '', allExtensions)
  const result = await window.electron.extensions.runProcess(
    ext.id,
    { file: inputFilePath },
    node.data.params
  )
  if (!result.success) throw new Error(result.error ?? 'Process extension failed')
  // result.result contains the processed file path
}

src/areas/workflows/nodes/ExtensionNode.tsx

The React component that renders extension nodes inside the visual workflow editor. It displays the extension name, configurable parameters, and connection pins (input/output sockets) based on the extension's declared schema.

This component pulls the extension list from useExtensionsStore and resolves output types to color-code connection handles in the node graph.

Built-in Process Extensions

Modly ships with several built-in process extensions located in src/areas/workflows/nodes/*/processor.*. These follow the same runtime contract as external extensions but reside in the builtin-extensions folder.

Key examples include:

Each processor reads incoming files, executes Python routines, and returns processed assets that downstream nodes consume.

Extension Lifecycle in Modly

The extension system follows a five-stage lifecycle:

  1. Discovery – On startup, extensionsStore.loadExtensions() invokes window.electron.extensions.list(). The main process scans extensionsDir, validates each manifest.json, and returns typed arrays of ModelExtension or ProcessExtension objects.

  2. Installation – Calling extensionsStore.installFromGitHub(url) triggers the Electron bridge to clone the repository, run install scripts, and stream progress events (downloading, extracting, validating, setting_up).

  3. Workflow Integration – Dragging an Extension Node into the visual editor creates a node with data.extensionId set to the extension identifier (e.g., pack/process-node).

  4. Execution – workflowRunStore iterates through nodes; for extensionNode types, it calls window.electron.extensions.runProcess(extensionId, input, params), launching the Python entry point defined in the manifest.

  5. Result Propagation – Processed assets feed back into the workflow graph, allowing downstream nodes like Mesh Exporter to consume the output.

await useExtensionsStore.getState().installFromGitHub(
  'https://github.com/lightningpixel/modly-hunyuan3d-mini-extension'
)

Summary

Frequently Asked Questions

How does Modly validate extension manifests before execution?

The src/areas/workflows/preflight.ts module performs static analysis on workflow graphs before runtime. It uses getWorkflowExtension to verify that every extensionNode references a valid extension ID and that the node's inputs and outputs match the types declared in the extension's manifest.json. Failed validations surface as UI warnings rather than runtime crashes.

What is the difference between model and process extensions in the Modly extension system?

Model extensions typically load AI models or specialized processing capabilities that run inference tasks, while process extensions handle data transformations like mesh optimization or file format conversion. Both follow the same IPC contract defined in electron.d.ts, but they populate separate arrays in extensionsStore.ts (modelExtensions vs processExtensions) to categorize their capabilities in the UI.

How do I install a third-party extension from GitHub in Modly?

Use the installFromGitHub method from the extensions store: await useExtensionsStore.getState().installFromGitHub('https://github.com/user/repo'). The main process clones the repository, validates the manifest.json, runs any defined install scripts, and streams progress events back to the UI through the onInstallProgress listener.

Where are built-in extensions located compared to external ones?

Built-in extensions reside in the src/areas/workflows/nodes/ directory within the application source (e.g., mesh-optimizer/processor.ts), while external extensions are cloned into the configured extensionsDir folder at runtime. Both types implement the same interface, but built-in extensions ship with the application and do not require separate installation through the GitHub workflow.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →