Skip to main content

Goal

Use iii worker add ./path to register a local worker project as a managed sandbox worker connected to the engine — no containers or Dockerfiles needed.

Context

Local-path workers are first-class managed workers with the same lifecycle as container workers (add, start, stop, remove, list). Each worker runs inside a lightweight microVM with its own filesystem, network, and dependencies. The CLI detects local paths automatically — any argument starting with ., /, or ~ is treated as a local directory. Requires macOS Apple Silicon or Linux with KVM.

What is a sandbox?

A sandbox is a hardware-isolated microVM powered by libkrun. Each sandbox has its own root filesystem, network stack, and process tree — completely separate from the host and from other workers. The engine manages the VM lifecycle, so you interact with sandboxed workers through the same iii worker commands you use for container workers.

Steps

1. Create a Worker Project

The CLI auto-detects your project type from well-known files and infers setup, install, and start commands.
Project typeDetected viaDefault package manager
Node.js / TypeScriptpackage.jsonnpm (or bun if bun.lock exists)
Pythonpyproject.toml or requirements.txtpip
RustCargo.tomlcargo
With auto-detection, you can add a worker immediately:
iii worker add ./my-project

2. Add a Manifest

Create an iii.worker.yaml at the root of your worker folder to configure the sandbox:
iii.worker.yaml
name: my-worker
runtime:
  language: typescript
  package_manager: npm
  entry: src/index.ts
resources:
  memory: 2048
  cpus: 2
scripts:
  setup: "apt-get update && apt-get install -y build-essential"
  install: "npm install"
  start: "npx tsx src/index.ts"
env:
  MY_API_KEY: sk-abc123
  LOG_LEVEL: debug

Manifest Fields

FieldRequiredDefaultDescription
nameYesWorker name (used as the identifier in config.yaml)
runtime.languageNotypescripttypescript, javascript, python, or rust
runtime.package_managerNonpm, yarn, pnpm, or bun (Node.js only)
runtime.entryNoEntrypoint file
resources.memoryNo2048Memory in MiB allocated to the sandbox VM
resources.cpusNo2Number of vCPUs allocated to the sandbox VM
scripts.setupNoinferredOne-time system setup (runs only on first start)
scripts.installNoinferredDependency installation command
scripts.startNoinferredWorker start command
env.*NoCustom environment variables injected into the sandbox
III_URL and III_ENGINE_URL are set automatically and cannot be overridden through the manifest.
If the scripts block is omitted entirely, commands are inferred from runtime.language, runtime.package_manager, and runtime.entry. For example, a TypeScript project using npm with entry src/index.ts infers npm install for install and npx tsx src/index.ts for start.

3. Add the Worker

iii worker add ./my-project
The CLI validates the directory, loads the manifest (or auto-detects the project type), prepares an isolated rootfs, copies your project files into the sandbox, runs setup and install scripts, and registers the worker in config.yaml with a worker_path: field:
config.yaml
workers:
  - name: my-worker
    worker_path: /absolute/path/to/my-project
If the engine is already running, the worker auto-starts immediately after being added.

CLI Flags

FlagDescription
--force, -fDelete existing artifacts and re-add the worker from scratch
--reset-configAlso remove the existing config.yaml entry before re-adding (requires --force)
Examples:
# Force a clean re-add (re-runs setup and install)
iii worker add ./my-project --force

# Re-add and also reset the config.yaml entry
iii worker add ./my-project --force --reset-config

4. Manage the Worker

Local-path workers support the same lifecycle commands as container workers:
# List all workers (includes a TYPE column: Local, OCI, Binary, Config)
iii worker list

# Stop a running worker
iii worker stop my-worker

# Start a stopped worker
iii worker start my-worker

# Remove a worker (deletes config.yaml entry and cached artifacts)
iii worker remove my-worker

5. Understand Dependency Caching

Each sandbox is cached at ~/.iii/managed/<worker-name>/. The caching lifecycle works as follows: First start — the CLI clones a base rootfs, copies your project into the sandbox, runs the setup and install scripts, then starts the worker. A marker file is written to signal that dependencies are installed. Subsequent starts — setup and install are skipped entirely. Only the project files are re-copied and the start script runs, making restarts fast. --force re-add — running iii worker add ./my-project --force deletes the cached sandbox at ~/.iii/managed/<worker-name>/ and re-runs the full setup from scratch. Use this when you change dependencies, update the base image, or modify install scripts.
When copying your project into the sandbox, the following directories are excluded automatically: node_modules, .git, target, __pycache__, .venv, dist.

6. Check Platform Requirements

Intel Macs are not supported. The microVM requires hardware virtualization only available on Apple Silicon or Linux with KVM.
macOS (Apple Silicon) — uses Hypervisor.framework. On first run, the CLI automatically codesigns itself with Hypervisor entitlements. This may prompt for confirmation. Linux — requires /dev/kvm to be accessible with read and write permissions. Verify with:
ls -l /dev/kvm

Result

Your worker runs inside an isolated microVM connected to the engine. The sandbox has its own filesystem, network stack, and process tree. The worker is registered in config.yaml and managed through the standard iii worker lifecycle commands — start, stop, list, and remove. To rebuild the sandbox after changing dependencies, re-add the worker with iii worker add ./my-project --force.