How to Develop a New Extension for Modly: A Complete Guide

You develop a Modly extension by creating a self-contained GitHub repository with a manifest.json file and an entry script—JavaScript for process extensions or Python for model extensions—then installing it via the Models tab using the repository URL.

Modly’s plugin architecture allows developers to extend the application’s capabilities by adding custom process or model extensions that integrate directly into the visual workflow editor. The core application discovers these extensions at runtime by cloning repositories into the local extensions directory and validating their manifests against a strict schema.

Extension Types and Architecture

Modly supports two distinct extension types, each serving different purposes in the workflow pipeline.

Process Extensions

Process extensions handle data transformation and manipulation within workflows. These execute JavaScript or TypeScript code to receive input from previous nodes, perform computations, and return results to downstream nodes. The backend loads these via the IPC bridge defined in electron/preload/electron-api.ts, specifically through the extensions.runProcess method.

Model Extensions

Model extensions provide AI-powered generation capabilities, typically involving Python-based machine learning models. These require a generator.py file containing a class that inherits from Modly’s BaseGenerator interface. The class specified in the manifest’s generator_class field is instantiated by the backend to process inputs and return generated assets like 3D meshes.

Creating the Extension Repository Structure

Every Modly extension must follow a specific repository layout to pass validation and load correctly.

The manifest.json Schema

The manifest.json file in your repository root defines the extension’s metadata and entry points. According to the validation logic in electron/main/extension-install-utils.ts (specifically the validateInstallManifest function), the manifest must include these required fields:

{
  "id": "my-awesome-extension",
  "type": "process",
  "entry": "processor.js",
  "generator_class": "MyGenerator",
  "nodes": [{ "id": "my-node" }]
}
  • id: A unique identifier across all installed extensions
  • type: Either "process" or "model", determining the validation path
  • entry: The executable file path (defaults to processor.js)
  • generator_class: Required only for model extensions; specifies the Python class name to instantiate
  • nodes: An array defining the node types this extension contributes to the workflow editor

Repository Layout Requirements

For process extensions, your repository must contain:

  • manifest.json with "type": "process"
  • The entry JavaScript file specified in the entry field

For model extensions, your repository must contain:

Implementing Process Extensions

Process extensions export an async function named run that receives input data and parameters from the workflow node.

Create a processor.js file implementing this signature:

// processor.js – minimal process extension
export async function run(input, params) {
  // input: data from previous node (e.g., image buffer)
  // params: node-specific configuration values
  const result = await performTransformation(input, params);
  return { text: result.summary };
}

The return object’s shape must match the expectations of workflowRunStore, which processes the result and passes it to subsequent nodes. The function runs inside the Electron main process via the IPC bridge exposed in electron/preload/electron-api.ts, allowing access to Node.js APIs and external libraries.

Implementing Model Extensions

Model extensions require Python code that implements the BaseGenerator interface from the modly_api package.

Create a generator.py file with a class matching your generator_class manifest field:


# generator.py – minimal model extension

from modly_api import BaseGenerator

class MyGenerator(BaseGenerator):
    def generate(self, image_path: str) -> str:
        # Process the input image with your ML model

        mesh_path = run_inference_and_export_glb(image_path)
        return mesh_path

The backend validates that generator.py exists during installation (checked in extension-install-utils.ts) and dynamically imports the specified class. The generate method receives the input file path and must return the path to a generated asset (typically a .glb mesh file).

Installing and Testing Your Extension

Local Development Testing

To test your extension before publishing:

  1. Clone your extension repository into the Modly extensions directory at $HOME/.modly/extensions
  2. Launch Modly in development mode: npm run dev
  3. Open the Workflow editor and add a node corresponding to your extension type
  4. Select your extension from the node-type dropdown
  5. Execute the workflow and monitor the console or UI logs (accessible at extensions/errors) for validation messages

Installing from GitHub

Once tested, push your repository to GitHub. Users (or yourself on other machines) can install it via the UI:

  1. Open Modly and navigate to the Models tab
  2. Click Install from GitHub
  3. Paste the HTTPS URL of your extension repository
  4. Modly clones the repo, validates the manifest.json, compiles the entry file if necessary, and registers the extension

The installation process uses the methods exposed through electron/preload/electron-api.ts, including extensions.installFromGitHub and extensions.reload.

Summary

  • Modly extensions are self-contained GitHub repositories with a mandatory manifest.json file validated by electron/main/extension-install-utils.ts
  • Process extensions use JavaScript entry files exporting a run(input, params) function and integrate via workflowRunStore
  • Model extensions use Python classes inheriting from BaseGenerator with a generate() method, specified via the generator_class manifest field
  • Extensions install into $HOME/.modly/extensions and are discovered at runtime by the IPC bridge in electron/preload/electron-api.ts
  • Testing locally requires cloning to the extensions folder and running Modly in development mode

Frequently Asked Questions

What file structure is required for a Modly extension?

A valid extension requires a manifest.json in the repository root plus an entry file appropriate to the type. Process extensions need a JavaScript file (default processor.js) exporting a run function, while model extensions require a generator.py containing a class that extends BaseGenerator. The manifest.json must declare all required fields including id, type, and either entry or generator_class depending on the extension type.

How does Modly validate extension manifests?

The validateInstallManifest function in electron/main/extension-install-utils.ts validates every manifest against a strict schema. It checks that required fields exist, that the type is either "process" or "model", and that appropriate complementary fields are present (e.g., generator_class for model types). Validation failures surface in the UI through the extensions/errors interface, preventing malformed extensions from loading.

Can I use TypeScript for process extensions?

Yes, you can write process extensions in TypeScript. Modly compiles the entry file during installation if necessary. Ensure your manifest.json points to the compiled JavaScript output or the TypeScript source if the build process handles transpilation. The exported run function must remain the default export regardless of the language used.

How do I debug a Modly extension during development?

Debug by running Modly in development mode (npm run dev) with your extension cloned into $HOME/.modly/extensions. Use the Workflow editor to instantiate your node and execute test runs. Check the Electron console and the dedicated extensions/errors view in the UI for validation errors or runtime stack traces. You can reload extensions dynamically using the extensions.reload method exposed in electron/preload/electron-api.ts without restarting the application.

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 →