engine: url: ws://127.0.0.1:49134 registration_namespace_grace_ms: 5000 workers: configuration: adapter: name: fs config: directory: ./config iii-worker-manager: host: 127.0.0.1 port: 49134 iii-http-functions: {} iii-stream: host: 127.0.0.1 port: 3112 iii-sandbox: auto_install: true ``` `engine.url` defaults to `ws://127.0.0.1:49134`. Compose writes the engine-only representation to `~/.iii/compose/<daemon-namespace>/engine-config.yaml` with owner-only permissions and starts the engine from i...
Scanned 9/3/2026
Install to Claude Code
npx -y skills add iii-hq/iii --skill upgrading --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Upgrading?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/iii-hq-upgrading-d2371d9f)More formats (shields.io, HTML) on the badges page.
<!-- generated by iii-skill-render. DO NOT EDIT (changes here are overwritten on the next render). Edit docs/next/upgrading/workers-to-compose.mdx. -->
iii 0.23 removes the legacy worker lifecycle. There is no compatibility period or automatic
migrator: `iii worker`, the `worker::*` functions, engine fallback through `iii.toml`, and
engine-managed project workers are gone.
A managed project now has one `worker-compose.yaml`. Its `engine:` section configures the engine;
`containers:` declares project workers. If a direct `config.yaml` still declares a project worker,
startup and reload stop with `UNSUPPORTED_CONFIG_WORKERS` and list every entry to migrate.
## Back up the project
Keep a copy of:
- `config.yaml` and any path passed with `--config`
- an existing `worker-compose.yaml`
- the configuration worker's storage directory, `./config/` by default
- state, queue, and stream data paths
- `iii.lock`, if the project used the removed installer
Rollback requires those files and the previous iii binary. The 0.23 engine does not accept the old
project-worker declarations.
## Build the new engine section
Move these five engine-owned worker configs from list entries in `config.yaml` to the direct
`engine.workers` map:
| Worker | Why it remains engine-owned |
| --- | --- |
| `configuration` | Owns schemas, values, and change notifications used by engine and project workers. |
| `iii-worker-manager` | Owns engine WebSocket and RBAC listeners. |
| `iii-http-functions` | Provides outbound HTTP functions inside the engine process. |
| `iii-stream` | Uses engine internals and engine-owned adapters. |
| `iii-sandbox` | Owns the builtin sandbox lifecycle. |
The map value is the worker config itself; do not keep the old nested `config:` key. Multiple
instances use a `#instance` suffix, such as `iii-worker-manager#rbac`.
```yaml worker-compose.yaml
# namespace: default
engine:
url: ws://127.0.0.1:49134
registration_namespace_grace_ms: 5000
workers:
configuration:
adapter:
name: fs
config:
directory: ./config
iii-worker-manager:
host: 127.0.0.1
port: 49134
iii-http-functions: {}
iii-stream:
host: 127.0.0.1
port: 3112
iii-sandbox:
auto_install: true
```
`engine.url` defaults to `ws://127.0.0.1:49134`. Compose writes the engine-only representation to
`~/.iii/compose/<daemon-namespace>/engine-config.yaml` with owner-only permissions and starts the
engine from it. Do not edit that generated file.
Remove explicit `iii-engine-functions`, `iii-telemetry`, and `iii-observability` entries. The
engine injects them automatically, and declaring one under `engine.workers` fails.
## Move project workers to containers
| Old name | Compose package/configuration id |
| --- | --- |
| `iii-http` or `http` | `http` |
| `iii-cron` or `cron` | `cron` |
| `iii-queue` or `queue` | `queue` |
| `iii-state` or `state` | `state` |
| `iii-pubsub` or `pubsub` | `pubsub` |
| `iii-bridge` | `bridge` |
| `iii-exec` | no package; use Compose `scripts` |
Copy each old project worker's `config:` value to `config_override`, preserve its storage paths,
and pin the package version.
```yaml worker-compose.yaml
containers:
state:
worker: package://api.workers.iii.dev/state
version: "0.22.2"
config_name: state
config_override:
adapter:
name: kv
config:
store_method: file_based
file_path: ./data/state_store.db
http:
worker: package://api.workers.iii.dev/http
version: "0.21.3"
config_name: http
config_override:
host: 127.0.0.1
port: 3111
app:
worker: path://.
start_after: [state, http]
scripts:
pre_run: pnpm build
run: pnpm start
post_run: pnpm cleanup
```
Translate `iii-exec` commands into `pre_run`, `run`, and `post_run`. Custom local workers use
`path://`; registry workers use `package://` plus a version.
You can also add a registry worker after the managed daemon is running:
```bash
iii trigger -n dev compose::add worker=http
iii trigger -n dev compose::add worker=state
```
`compose::add` writes `containers:` and restarts affected containers. It never edits `engine:` or
restarts the engine. A registry root of kind `engine` is rejected and points to
`engine.workers.<name>` when the worker is configurable.
## Preserve stored configuration
Standalone packages use unprefixed configuration ids. A value stored as `iii-state` is not copied
to `state` automatically.
1. Before upgrading, read the old value with `configuration::get`.
2. Put it under `config_override`, or write it to the new id with `configuration::set`.
3. Verify the new worker before removing the old stored entry.
Do not rename only the YAML file: filesystem-backed entries also contain id and schema metadata.
## Start the result
For a managed engine, the file owns both lifecycles:
```bash
iii compose --namespace dev --up --file worker-compose.yaml
```
The explicit namespace (`dev`) addresses `compose::*` and overrides the file's `namespace:` for
its containers. Changing `engine:` while the daemon runs returns `ENGINE_RESTART_REQUIRED`; stop
and restart that Compose invocation. A second file with `engine:` returns `ENGINE_ALREADY_OWNED`.
For an engine supervised separately by systemd or Kubernetes, keep its five allowed workers in
the list-shaped `config.yaml`, start it directly, omit `engine:` from the Compose file, and supply
the existing URL:
```bash
iii --config config.yaml
iii compose --namespace dev --engine ws://127.0.0.1:49134 --up --file worker-compose.yaml
```
Run those commands under separate supervisors. Explicit `--engine` has highest priority and may
override an `engine.url` in the Compose file. Without either value, Compose uses `III_URL`, then
defaults to `ws://127.0.0.1:49134`.
Verify the migration:
```bash
iii trigger -n dev compose::status file=worker-compose.yaml
iii trigger engine::workers::list
iii trigger engine::triggers::list
```
## Common errors
- `UNSUPPORTED_CONFIG_WORKERS`: direct `config.yaml` still contains project workers.
- `UNSUPPORTED_ENGINE_WORKER`: `engine.workers` contains a project or unknown worker.
- `ENGINE_WORKER_IS_INJECTED`: remove an automatically supplied internal worker.
- `ENGINE_RESTART_REQUIRED`: restart Compose to apply a changed engine section.
- `ENGINE_ALREADY_OWNED`: start the second managed file in a separate Compose invocation.
- `ENGINE_SECTION_REQUIRES_MANAGED_START`: an external daemon was asked to load a managed file.
- `ENGINE_WORKER_IS_BUILTIN`: `compose::add` was given an engine package as a root.
- `CONTAINER_NAME_TAKEN`: another live process owns the same `(namespace, worker name)`.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!