Skip to content

Plugin structure

Under the hood, a .lia file is a ZIP archive with a fixed structure. Liatir validates the bundle signature before reading the manifest or executing any runtime payload.

Runtime variants

There are two supported runtimes: Node and WASM.

Node plugins should not maintain a hand-written .lia-manifest.json. liatir build generates the manifest from the exported definePlugin({...}) contract.

WASM plugins do use .lia-manifest.json, because Rust/WASM cannot export the JavaScript plugin contract at build time.

Generated Node manifest

For Node plugins, the manifest is generated by liatir build after bundling and validating the default export.

Manifest example:

json
{
  "name": "my-plugin",
  "version": "1.0.0",
  "description": "What this plugin does",
  "runtime": "node",
  "category": "Utilities",
  "tags": ["text"],
  "inputSchema": {
    "text": {
      "type": "string",
      "label": "Text",
      "description": "Field description.",
      "required": true,
      "default": "hello from Liatir"
    }
  },
  "outputSchema": {
    "length": {
      "type": "number",
      "label": "Length",
      "description": "Field description.",
      "format": "integer"
    }
  }
}

Node entry point (index.ts or .js)

Keep the entry point clean and do not alter its structure, or Liatir will reject the plugin. Organize your source files in the project's src/ folder and keep the entry point as a thin wrapper that exports the plugin logic.

ts
import { definePlugin, field, type PluginContext } from "@liatir/api";

const liatirPlugin = definePlugin({
  inputs: {
    text: field.string({
      label: "Text",
      description: "Text to analyze.",
      required: true,
      default: "hello from Liatir",
    }),
  },
  outputs: {
    length: field.number({
      label: "Length",
      description: "Number of characters in the input text.",
      format: "integer",
    }),
  },
});

export default liatirPlugin.main(async ({ input, Liatir }: PluginContext<typeof liatirPlugin>) => {

  // Your logic

  return {
    length: input.text.length,
  };
});

liatir build rejects Node plugins that export an invalid contract.

Field schemas

Input fields can be of type:

  • string
  • number
  • boolean
  • file

Output fields can be of type:

  • string
  • number
  • boolean
  • file
  • stats
  • json

Shared field properties include:

PropertyDescription
labelHuman-readable label shown in the UI.
descriptionShort explanation shown near the field.
requiredWhether the field must be set before running.
defaultDefault value applied by the UI and by liatir dev.
acceptAccepted file extensions for file inputs.
extExpected file extensions for file outputs.
formatNumeric output display hint: integer, decimal, percent, or bytes.

File outputs

If an output field has type: "file", the returned value can either reference an existing file path or provide inline content for Liatir to persist.

ts
return {
  report: {
    content: "sample,score\nA,0.92\n",
    fileName: "report.csv",
  },
};

Liatir registers saved file outputs under the workspace's Results folder so they can be opened later or connected to downstream pipeline steps.

WASM manifest

WASM plugins keep their schema in .lia-manifest.json:

json
{
  "name": "wasm-length",
  "version": "1.0.0",
  "description": "Count characters in text.",
  "runtime": "wasm",
  "inputSchema": {
    "text": { "type": "string", "label": "Text", "required": true }
  },
  "outputSchema": {
    "length": { "type": "number", "label": "Length", "format": "integer" }
  }
}

The WASM binary reads JSON input from stdin and writes JSON output to stdout. Liatir rejects WASM plugins that do not follow the I/O contract.

Liatir — powerful bioinformatics on your machine.

By using this app, you agree to our Privacy Policy and Terms of Service.