Skip to main content

Documentation Index

Fetch the complete documentation index at: https://motiadev-docs-verdict-review-plan.mintlify.app/llms.txt

Use this file to discover all available pages before exploring further.

Goal

Use the iii worker commands to manage container workers throughout their lifecycle — from adding an image to monitoring logs and removing workers you no longer need.

Context

Container workers are OCI images that the engine pulls, extracts, and runs in isolated sandboxes. The iii worker CLI manages these workers declaratively through config.yaml, so you rarely need to edit configuration files by hand. Registry-managed workers can also be pinned in iii.lock for reproducible installs.

Steps

1. Add a Worker

Pull an image from a registry and register it in config.yaml:
# From the iii registry (shorthand)
iii worker add image-resize

# From any OCI registry
iii worker add ghcr.io/my-org/my-worker:latest
The command resolves the image, pulls it, and appends an entry to config.yaml:
config.yaml
workers:
  - name: image-resize
    image: ghcr.io/iii-hq/image-resize:1.0.0
If the image contains a /iii/worker.yaml manifest with resources hints, they are included automatically. Once defined in config.yaml, all workers start automatically when you run iii. If you make changes to the workers list, simply restart iii to pick them up — no extra commands needed.

2. Configure Environment and Resources

Edit config.yaml to pass environment variables or set resource limits:
config.yaml
workers:
  - name: image-resize
    image: ghcr.io/iii-hq/image-resize:1.0.0
    config:
      # Remapping environment variables
      MY_API_KEY: ${MY_API_KEY}
      LOG_LEVEL: debug
Values under config: are flattened and injected as environment variables when the worker starts. Changes take effect the next time the worker starts (restart iii to apply).

3. Remove a Worker

Remove a worker and its entry from config.yaml:
iii worker remove image-resize
The cached image layers remain on disk.

4. Manage Individual Workers (Optional)

If you need fine-grained control over workers while iii is already running, the CLI provides commands to manage them individually. These are optional — restarting iii always starts every worker defined in config.yaml.
# List all registered workers and their status
iii worker list

# Start a previously stopped worker
iii worker start image-resize

# Stop a running worker without removing it
iii worker stop image-resize

# Stream logs from a running worker
iii worker logs image-resize

# Follow log output in real time
iii worker logs image-resize --follow

5. Exec into a Running Worker

Run a command inside a running worker’s microVM — useful for debugging crashed handlers, inspecting guest filesystem state, running ad-hoc scripts, or opening an interactive shell. Behaves like docker exec: stdin/stdout/stderr flow through, the child’s exit code becomes the CLI’s exit code.
# Run a one-shot command
iii worker exec image-resize -- ls -la /workspace

# Set environment variables and a working directory
iii worker exec image-resize -e LOG_LEVEL=debug -w /tmp -- ./probe

# Kill the command after 30 seconds (exits with code 124 on timeout)
iii worker exec image-resize --timeout 30s -- ./long-task

# Interactive shell (TTY auto-detected when run in a terminal)
iii worker exec image-resize -- sh
When both stdin and stdout are terminals, iii worker exec automatically allocates a pseudo-terminal — line editing, job control, and prompts all work. The moment either stream is redirected or piped (... -- cmd | tee log, ... -- cmd > out.txt, CI), pipe mode kicks back in so output stays byte-exact. Pass -t to force TTY, or --no-tty to force pipe mode in a terminal.
Signals and timeouts. Press Ctrl-C once to send SIGINT to the guest process; press it again within a second to escalate to SIGKILL and exit. --timeout accepts humantime syntax (30s, 5m, 1500ms); on expiry the client kills the guest session and exits with code 124, matching coreutils timeout(1). Flags:
FlagPurpose
-e KEY=VALUESet an env var in the spawned process. Repeatable.
-w PATHWorking directory inside the guest. Defaults to /workspace.
-t, --ttyForce TTY mode (required if stdin isn’t a terminal and you want one anyway).
--no-ttyForce pipe mode, disabling auto-detection.
--timeout DURATIONSIGKILL the child after DURATION; exit 124.

6. Build and Publish Your Own Image

To distribute a custom worker as an OCI image, create a project that uses an iii SDK, package it with a Dockerfile, and push it to a registry.

Write the Worker

src/index.ts
import { registerWorker, Logger } from 'iii-sdk'

const iii = registerWorker(process.env.III_URL ?? 'ws://localhost:49134')

iii.registerFunction('my-worker::hello', async (data) => {
  const logger = new Logger()
  logger.info('Hello from my OCI worker!', { input: data })
  return { message: 'Hello!' }
})

Create a Dockerfile

The image must define an ENTRYPOINT that starts the worker process. It should also declare ENV variables to configure how the worker connects to the engine. When you run iii worker add, the CLI extracts all ENV declarations from the OCI image and writes them as the config: block in config.yaml. This is how the image communicates its default configuration to the engine. For binary workers (e.g. Rust), also set CMD with --url so the runtime can patch the engine address at startup.
Dockerfile
FROM node:22-slim
WORKDIR /app
COPY package.json .
RUN npm install
COPY src/ src/

# Extracted by `iii worker add` and saved to config.yaml.
ENV FOO=bar

ENTRYPOINT ["npx", "tsx", "src/index.ts"]
Running iii worker add extracts all ENV declarations from the image (excluding system variables like PATH and HOME) and writes them under config: in config.yaml. You can then edit config.yaml to override any value. At startup, the runtime reads III_ENGINE_URL (or III_URL) from config: and uses it to connect the worker to the engine.

Build and Push

docker build -t my-worker:latest .

# Local registry (for development)
docker run -d -p 5050:5000 --name registry registry:2
docker tag my-worker:latest localhost:5050/my-worker:latest
docker push localhost:5050/my-worker:latest

# Remote registry (Docker Hub, GHCR, etc.)
docker tag my-worker:latest ghcr.io/my-org/my-worker:1.0.0
docker push ghcr.io/my-org/my-worker:1.0.0
Then add it to the engine:
iii worker add localhost:5050/my-worker:latest

Result

You can manage the full lifecycle of container workers — add, configure, start, stop, inspect logs, and remove — using the iii worker CLI. Worker configuration is tracked in config.yaml; registry-managed worker source pins can also be tracked in iii.lock. See Reproduce Worker Installs for the lockfile workflow.