Command line

Since version 2.3.1, you can use the command line to register your components and productions.

To use it, you have to use the following command :

iop 

output :

usage: python3 -m iop [-h] [-d [DEFAULT]] [-l] [-s [START]] [-S] [-k] [-r] [-x]
                      [-m MIGRATE] [-e [EXPORT]] [-v] [-L [LOG]] [-q [QUEUE]]
                      [-i [INIT]] [--bindings] [--unbind UNBIND] [-t [TEST]]
                      [-u] [-D] [-C [CLASSNAME]]
                      [-B [BODY]]

optional arguments:
  -h, --help            display help and default production name
  -d DEFAULT, --default DEFAULT
                        set the default production
  -l, --list           list productions
  -s START, --start START
                        start a production
  -S, --stop           stop a production
  -k, --kill           kill a production
  -r, --restart        restart a production
  -x, --status         status a production
  -m MIGRATE, -M MIGRATE, --migrate MIGRATE
                        migrate production and classes with settings file
  -e EXPORT, --export EXPORT
                        export a production
  -v, --version        display version
  -L, --log           display log
  -q [QUEUE], --queue [QUEUE]
                        display runtime queue information
  -i INIT, --init INIT
                        init the iop module in iris
  --bindings          list IOP-generated IRIS proxy class bindings
  --unbind UNBIND     remove an IOP-generated IRIS proxy class binding
  -t TEST, --test TEST
                        test the iop module in iris

start arguments:
  -D, --detach         start a production in detach mode

test arguments:
  -C CLASSNAME, --classname CLASSNAME
                        test classname
  -B BODY, --body BODY
                        test body

bindings arguments:
  --unused            with --bindings, show only proxy classes unused by productions

default production: IoP.Production

Terminology

The CLI uses these terms consistently:

  • migrate: apply a Python migration file to IRIS. This can register classes, schemas, and productions.
  • plan: compare a desired Python Production with the current IRIS production and write a reviewable change plan.
  • apply plan: apply supported safe plan operations. Destructive operations are skipped unless explicitly allowed.
  • bind or register: create an IRIS proxy class that points to a Python component class.
  • unbind or unregister: remove an IOP-generated IRIS proxy class binding. This does not delete Python source files or production items.

help

The help command display the help and the default production name.

iop -h

output :

usage: python3 -m iop [-h] [-d DEFAULT] [-l] [-s START] [-S] [-k] [-r] [-x] [-m MIGRATE]
                      [-e EXPORT] [-v] [-L] [-i INIT] [-t TEST] [-D] [-C CLASSNAME] [-B BODY]
...
default production: IoP.Production

default

The default command set the default production.

With no argument, it display the default production.

iop -d

output :

default production: IoP.Production

With an argument, it set the default production.

iop -d IoP.Production

list

The list command lists productions.

iop -l

output :

{
    "IoP.Production": {
        "Status": "Stopped",
        "LastStartTime": "2023-05-31 11:13:51.000",
        "LastStopTime": "2023-05-31 11:13:54.153",
        "AutoStart": 0
    }
}

start

The start command starts a production.

To exit the command, you have to press CTRL+C (unless using detach mode).

iop -s IoP.Production

You can start a production in detach mode using the -D flag:

iop -s IoP.Production -D

In detach mode, the production starts and the command returns immediately without showing logs.

kill

The kill command kill a production (force stop).

Kill command is the same as stop command but with a force stop.

Kill command doesn't take an argument because only one production can be running.

iop -k 

stop

The stop command stop a production.

Stop command doesn't take an argument because only one production can be running.

iop -S 

restart

The restart command restart a production.

Restart command doesn't take an argument because only one production can be running.

iop -r 

migrate

The migrate command applies a Python migration file to IRIS. A migration can bind Python components as IRIS proxy classes, register schemas, and save production definitions. The file can be named settings.py, but it can also be a single-file production such as demo.py.

The migration file path can be relative or absolute.

iop -m /tmp/settings.py
iop -m /tmp/demo.py

The migration file is imported by Python. Put executable code such as prod.test(...), prod.start(), or ad hoc scripts behind an if __name__ == "__main__": guard so migration can inspect PRODUCTIONS without running the script.

Use --dry-run or --explain to validate the settings file and show the migration plan without writing to IRIS:

iop -M /tmp/settings.py --dry-run

The plan uses the same sections as the migration file: CLASSES, SCHEMAS, PRODUCTIONS. Entries in CLASSES are annotated as components or PersistentMessage classes. Migration output includes the mode, namespace, and a final Migration succeeded line when the migration completes.

For new Python-authored production components, prefer Production objects in PRODUCTIONS; use CLASSES for standalone bindings, native PersistentMessage classes, and legacy migration files.

Production validation warns by default. Pass --strict-production-validation to fail the dry-run or migration when validation reports an issue:

iop -M /tmp/settings.py --strict-production-validation

More details about the settings file can be found here.

Remote migrate

If the migration file contains a REMOTE_SETTINGS dict, the migration is performed against the remote IRIS instance automatically — no environment variables needed:

# settings.py
from iop import Production


REMOTE_SETTINGS = {
    "url": "http://localhost:52773",
    "username": "admin",
    "password": "password",
    "namespace": "USER",
}

prod = Production("Demo.Production", testing_enabled=True)
# Add services, processes, operations, and connections here.

PRODUCTIONS = [prod]

To disable remote mode and run the migration locally even when REMOTE_SETTINGS is present or IOP_URL is set, pass --force-local:

iop -M /tmp/settings.py --force-local

--force-local disables remote mode for all commands, not only migrate.

bindings and unbind

List generated proxy class bindings:

iop --bindings

List only proxy classes that are not used by any production item:

iop --bindings --unused

The unbind command removes one IOP-generated IRIS proxy class binding:

iop --unbind Python.WrongOperation

Unbind only removes the generated IRIS class. It does not delete Python source files and it does not remove production items. If any production item still uses the proxy class, the command fails and reports the production item references. Remove or change those production items first, then run --unbind again.

plan, review, apply, verify, rollback

The plan workflow is the conservative way to change an existing IRIS production from a Python Production definition. It is useful when the deployed production may contain ObjectScript classes, BPL, DTL, routing rules, dynamic targets, or settings that Python cannot fully reconstruct yet.

Build a plan:

iop --plan /path/to/settings.py \
    --production Demo.Production \
    --out plan.json

Review the saved plan:

iop --review-plan plan.json

Apply supported safe operations locally:

iop --apply-plan plan.json \
    --settings /path/to/settings.py \
    --backup-dir .iop/backups

Verify after apply:

iop --verify-plan plan.json

Rollback restores the full production export saved before apply and therefore requires explicit destructive approval:

iop --rollback-backup .iop/backups/20260604T120000Z-abc123def456 \
    --allow-destructive

Default apply behavior:

  • Safe operations are applied.
  • Deletes, removals, and class replacements are skipped unless --allow-destructive is passed.
  • Runtime-only or dynamic routes with no source setting are always skipped.
  • A backup directory is written before any mutation.
  • Remote REST apply and rollback are blocked in v1.

See Production Change Workflow for the full policy and Python API.

init

The init command initializes the IoP module in IRIS by loading and compiling the bundled .cls files.

iop -i

In local mode this calls %SYSTEM.OBJ.LoadDir + %SYSTEM.OBJ.Compile directly via the embedded Python binding.

In remote mode the same .cls files are uploaded file-by-file via the Atelier REST API (PUT /api/atelier/v1/{namespace}/doc/{name}) and then compiled in a single batch request (POST /api/atelier/v1/{namespace}/action/compile).

You can also point to a custom directory of .cls files:

iop -i /path/to/my/cls

Remote init: Python package prerequisite

iop -i only handles the ObjectScript side (.cls files). The iop Python package itself must also be installed in the remote IRIS Python environment — the CLI cannot do this automatically because there is no REST endpoint to run pip install on the IRIS server.

Install it once on the server using the IRIS-bundled Python interpreter:

# On the machine running IRIS (or via docker exec / SSH)
python3 -m pip install iris-pex-embedded-python

Native PersistentMessage support also requires iris-persistence in that same server-side Python environment. It is installed automatically with current iris-pex-embedded-python package metadata; for older deployments, install it explicitly:

python3 -m pip install "iris-persistence>=0.1.0"

Recommended init sequence for a fresh remote IRIS instance: ```bash

1. Upload and compile the .cls files via Atelier API

iop -i

2. Install the iop Python package on the IRIS server (server-side, once)

python3 -m pip install iris-pex-embedded-python

3. Now migrate your project

iop -M /path/to/settings.py ```

test

The test command is a low-level helper for testing IoP components. You can optionally specify a test name, classname, and body.

Do not use iop --test as the normal way to test Business Services. Test services through the runtime director or production runtime API so the deployed production context, component settings, and configured targets are used.

Basic test:

iop -t

Test with specific classname:

iop -t MyTest -C MyClass

Test with body:

iop -t MyTest -C MyClass -B "test body"

export

The export command export a production.

If no argument is given, the export command export the default production.

iop -e

If an argument is given, the export command export the production given in argument.

iop -e IoP.Production

JSON is the default export format. It is useful for raw inspection and round-trip diagnostics, but it is not the recommended brownfield authoring artifact.

iop -e IoP.Production --format json

output:

{
    "Production": {
        "@Name": "IoP.Production",
        "@TestingEnabled": "true",
        "@LogGeneralTraceEvents": "false",
        "Description": "",
        "ActorPoolSize": "2",
        "Item": [
            {
                "@Name": "Python.FileOperation",
                "@Category": "",
                "@ClassName": "Python.FileOperation",
                "@PoolSize": "1",
                "@Enabled": "true",
                "@Foreground": "false",
                "@Comment": "",
                "@LogTraceEvents": "true",
                "@Schedule": "",
                "Setting": [
                    {
                        "@Target": "Adapter",
                        "@Name": "Charset",
                        "#text": "utf-8"
                    },
                    {
                        "@Target": "Adapter",
                        "@Name": "FilePath",
                        "#text": "/irisdev/app/output/"
                    },
                    {
                        "@Target": "Host",
                        "@Name": "%settings",
                        "#text": "path=/irisdev/app/output/"
                    }
                ]
            }
        ]
    }
}

For brownfield modernization, export a readable Python draft:

iop -e IoP.Production --format python > production_settings.py

The generated file uses the Production DSL with component(...) and connect(...) calls. Review it before migration because IRIS export cannot fully recover original Python classes, variable names, persistent message declarations, or every dynamic runtime route.

To generate a class-style declarative draft, use:

iop -e IoP.Production --format class > production_class_settings.py

The generated file uses Production subclasses with ComponentItem, ServiceItem, ProcessItem, OperationItem, and Route. It uses tuples for declaration attributes and string class names because exported IRIS metadata cannot reliably recover Python class objects. Imported items without explicit role metadata are emitted as ComponentItem; review item grouping, Python proxy TODOs, and inferred routes before migration.

You can inspect only the reconstructed route graph with:

iop -e IoP.Production --format graph

To export the same reconstructed draft graph as Mermaid flowchart text:

iop -e IoP.Production --format mermaid > production_graph.mmd

Mermaid export groups known services, processes, and operations from left to right.

status

The status command status a production.

Status command doesn't take an argument because only one production can be running.

iop -x 

output :

{
    "Production": "IoP.Production",
    "Status": "stopped"
}

Status can be : - stopped - running - suspended - troubled

queue

The queue command displays runtime queue counters for a production.

iop --queue IoP.Production

Without an argument, it uses the default production:

iop --queue

output :

{
    "production": "IoP.Production",
    "items": [
        {
            "item": "FileInput",
            "queue_name": "FileInput",
            "count": 0,
            "exists": true
        }
    ]
}

version

The version command display the version.

iop -v

output :

2.3.0

log

The log command display the log.

To exit the command, you have to press CTRL+C.

iop -L

output :

2021-08-30 15:13:51.000 [IoP.Production] INFO: Starting production
2021-08-30 15:13:51.000 [IoP.Production] INFO: Starting item Python.FileOperation
2021-08-30 15:13:51.000 [IoP.Production] INFO: Starting item Python.EmailOperation
...

Remote mode

Since version 3.6.0, the iop CLI can operate against a remote IRIS instance (e.g. a Docker container or a server) without requiring a local IRIS installation. All commands work in both local and remote mode.

Activation

Remote mode is activated automatically through any of these mechanisms (evaluated in priority order):

  1. IOP_URL environment variable — highest priority.
  2. -R / --remote-settings CLI flag — path to a settings.py with REMOTE_SETTINGS.
  3. IOP_SETTINGS environment variable — path to a Python file containing a REMOTE_SETTINGS dict.
  4. -m settings.py file — when the file passed to the migrate command contains a REMOTE_SETTINGS dict, remote mode is enabled automatically for the entire command.
Variable / flag Description Default
IOP_URL Base URL of the IRIS web server (e.g. http://localhost:52773)
-R FILE / --remote-settings FILE Path to a settings.py containing REMOTE_SETTINGS
IOP_USERNAME IRIS username
IOP_PASSWORD IRIS password
IOP_NAMESPACE IRIS namespace to operate in USER
IOP_VERIFY_SSL Set to false to disable TLS certificate verification true
IOP_SETTINGS Path to a Python settings file containing a REMOTE_SETTINGS dict

When none of the above resolve, the CLI operates in local mode (requires an active IRIS session).

Quick start with Docker

# Point the CLI at the IRIS container
export IOP_URL=http://localhost:52773
export IOP_USERNAME=admin
export IOP_PASSWORD=password
export IOP_NAMESPACE=USER

iop -x            # production status
iop -l            # list all productions
iop -s MyApp.Production   # start a production
iop -r            # restart
iop -S            # stop
iop -k            # kill
iop -u            # update (hot-reload changed items)
iop -L            # tail the production log
iop -q MyApp.Production   # runtime queue counters

Settings file

You can store remote connection details in a Python REMOTE_SETTINGS dict and reference the file via the -R flag or the IOP_SETTINGS environment variable.

Using the -R flag (recommended — takes priority over IOP_SETTINGS):

iop -x -R /path/to/settings.py
iop -l -R /path/to/settings.py
iop -M /path/to/settings.py -R /path/to/settings.py   # explicit > migrate fallback

Using the IOP_SETTINGS environment variable:

export IOP_SETTINGS=/path/to/settings.py

The settings file format is the same either way:

# settings.py - used by both migration and remote CLI
from iop import Production


REMOTE_SETTINGS = {
    "url":        "http://iris-server:52773",
    "username":   "admin",
    "password":   "password",
    "namespace":  "USER",
    "verify_ssl": True,
}

# Optionally also define a production graph for migration.
prod = Production("Demo.Production", testing_enabled=True)
PRODUCTIONS = [prod]

This is the same file format used by iop -m for migrations, so a single settings.py can serve both purposes: describe a production graph and how to reach the remote IRIS instance.

Namespace override

You can override the namespace for a single command with the -n / --namespace flag:

iop -x -n MYNS

Improved test command

In remote mode (and local mode) the -t command accepts a message body either inline or from a file:

# Inline JSON body
iop -t Python.MyOperation -C Python.MyRequest -B '{"key": "value"}'

# Body from a JSON file
iop -t Python.MyOperation -C Python.MyRequest -B @path/to/body.json

The response is pretty-printed:

classname: Python.MyResponse
body:
{
    "answer": 42
}

Disabling remote mode

Pass --force-local to any command to bypass remote mode entirely, even when IOP_URL, -R, IOP_SETTINGS, or REMOTE_SETTINGS in a settings file would otherwise activate it:

iop -x --force-local               # status using local IRIS session
iop -q --force-local               # queue counters using local IRIS session
iop -M settings.py --force-local   # local migration, ignore REMOTE_SETTINGS
iop -L --force-local               # tail local log
iop -x -R settings.py --force-local  # -R is ignored when --force-local is set

Current mode indicator

Running iop -h shows whether the CLI is in local or remote mode:

Mode: REMOTE (http://localhost:52773)