Documentation Index
Fetch the complete documentation index at: https://motiadev-chore-content-updates-2.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
Goal
Useiii 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 sameiii 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 type | Detected via | Default package manager |
|---|---|---|
| Node.js / TypeScript | package.json | npm (or bun if bun.lock exists) |
| Python | pyproject.toml or requirements.txt | pip |
| Rust | Cargo.toml | cargo |
2. Add a Manifest
Create aniii.worker.yaml at the root of your worker folder to configure the sandbox:
- Node.js / TypeScript
- Bun
- Python
- Rust
iii.worker.yaml
Manifest Fields
| Field | Required | Default | Description |
|---|---|---|---|
name | Yes | — | Worker name (used as the identifier in config.yaml) |
runtime.kind | No | typescript | typescript, javascript, bun, python, or rust. Older manifests with runtime.language still parse (with a deprecation warning) — rename to kind. |
runtime.package_manager | No | — | npm, yarn, pnpm, or bun (only for kind: typescript/javascript; kind: bun doesn’t need this) |
runtime.entry | No | — | Entrypoint file |
runtime.base_image | No | kind default | OCI image used as the sandbox rootfs. Overrides the per-kind default. Defaults: kind: typescript/javascript → iiidev/node:latest; kind: bun → oven/bun:latest; kind: python → iiidev/python:latest; kind: rust → library/rust:slim-bookworm. See Custom base images below. |
resources.memory | No | 2048 | Memory in MiB allocated to the sandbox VM |
resources.cpus | No | 2 | Number of vCPUs allocated to the sandbox VM |
scripts.setup | No | inferred | One-time system setup (runs only on first start) |
scripts.install | No | inferred | Dependency installation command |
scripts.start | No | inferred | Worker start command |
env.* | No | — | Custom environment variables injected into the sandbox |
Custom base images
By default iii picks a rootfs image perruntime.kind: iiidev/node:latest for typescript/javascript, oven/bun:latest for bun, iiidev/python:latest for python, library/rust:slim-bookworm for rust. Most of the time you won’t need base_image — just pick the right kind. Use base_image when you need a specific version (e.g. pin oven/bun:1.3.12) or a custom image with your team’s deps pre-baked:
iii.worker.yaml
base_image gets its own cache directory under ~/.iii/rootfs/<slug>/, so pinning a specific bun version won’t clobber the default oven/bun:latest rootfs used by other kind: bun workers. The image is pulled on first start and reused for every subsequent start that names the same image.
III_URL and III_ENGINE_URL are set automatically and cannot be overridden through the manifest.scripts block is omitted entirely, commands are inferred from runtime.kind, runtime.package_manager, and runtime.entry. For example, kind: typescript + package_manager: npm + entry: src/index.ts infers npm install for install and npx tsx src/index.ts for start. kind: bun + entry: src/index.ts infers bun install + bun run src/index.ts (no package_manager needed).
3. Add the Worker
config.yaml with a worker_path: field:
config.yaml
CLI Flags
| Flag | Description |
|---|---|
--force, -f | Delete existing artifacts and re-add the worker from scratch |
--reset-config | Also remove the existing config.yaml entry before re-adding (requires --force) |
4. Manage the Worker
Local-path workers support the same lifecycle commands as container workers: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
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:
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 inconfig.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.