Skip to content
Back to skills

Creating Workers

ASecurity

{/* Note: move this up */} The iii registry at [workers.iii.dev](https://workers.iii.dev/) is where published workers live so other iii projects can install them with `iii worker add <name>`.

  • 18,821 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added September 3, 2026
developmentjavascriptpythonjavashellnoderailsdockergit

Security analysis

A100/100

Pro scans all 9 files and shows the line behind each finding

Scanned September 3, 2026

npx -y skills add iii-hq/iii --skill creating-workers --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Creating Workers?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Creating Workers
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/iii-hq-creating-workers-dd7a40e2/badge)](https://www.skillsdirectory.com/skills/iii-hq-creating-workers-dd7a40e2)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
<!-- generated by iii-skill-render. DO NOT EDIT (changes here are overwritten on the next render). Edit docs/0-13-0/creating-workers/workers-registry.mdx. -->

# Registry


{/* Note: move this up */}

The iii registry at [workers.iii.dev](https://workers.iii.dev/) is where published workers live so
other iii projects can install them with `iii worker add <name>`.

## Publish a worker

Publishing a worker uploads its binary or OCI image to the registry, records its semver version, and
makes the worker installable by name from any iii project.

{/* TODO: capture the canonical publish command (likely `iii worker publish` or similar), the authentication requirements, and the metadata the registry expects (description, repo URL, supported platforms, etc.). */}

## Version your worker

Workers in the registry follow semver. Patch bumps for bug fixes, minor bumps for additive
capability, major bumps for breaking changes to function or trigger signatures.

{/* TODO: document how versions are tagged in the worker repo (git tag pattern), how the publish command resolves the version, and how to publish pre-releases. */}

## Build binary artifacts for multiple platforms

Binary workers can publish artifacts for multiple platform targets in a single registry entry (macOS
arm64/x64, Linux arm64/x64/armv7, Windows arm64/x64/x86). One published version covers every
supported host without separate publications per platform.

{/* TODO: document the cross-build flow, the supported target triples, how the artifacts are signed/checksummed, and where they're uploaded. */}

## Update or remove a published worker

{/* TODO: cover how to publish a new version (semver bump + republish), how to deprecate a worker, and whether/how a published version can be retracted (yanked). */}

## Bundle workers (tar.gz archives)

Bundle workers are a third artifact kind alongside `binary` and `image`. The registry serves a
single `tar.gz` archive that contains the worker's bundled source plus an `iii.worker.yaml`
manifest at the archive root. `iii worker add <name>` downloads, verifies a SHA-256 checksum,
extracts the archive into `~/.iii/workers-bundle/<name>/`, and runs it through the existing
libkrun rails (the same sandbox path used by local-path workers, minus the host-side source
watcher).

Use a bundle when:

- You ship a pre-built JavaScript bundle (`esbuild`, `tsdown`, `bun build`) or a packaged Python
  worker and don't want to publish a Docker image.
- You want artifacts measured in KB, not MB. Only the bundled source travels in the archive;
  the runtime ships with the engine-allowlisted base image (`docker.io/iiidev/node:latest` or
  `docker.io/iiidev/python:latest`).
- You want install to look identical to other registry workers from the user's perspective
  (`iii worker add my-worker`, same as binary and OCI).

### Registry response shape

```json
{
  "type": "bundle",
  "name": "my-worker",
  "version": "1.2.0",
  "archive_url": "https://cdn.workers.iii.dev/my-worker/1.2.0/bundle.tar.gz",
  "sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
}
```

The engine GETs `archive_url`, streams the bytes through a SHA-256 hasher, and compares against
`sha256`. Mismatches abort the install and delete the downloaded blob immediately.

### Archive layout

The archive root MUST contain `iii.worker.yaml`. Anything else sits at runtime-discoverable
paths from the bundle's perspective.

```text
my-worker-1.2.0.tar.gz
├── iii.worker.yaml
├── bundle.js
└── assets/
    └── ...
```

### Manifest contract (`iii.worker.yaml`)

Bundle manifests use a strict subset of the local-worker manifest. Three fields are explicitly
**rejected**:

- `scripts.setup`: would execute publisher-supplied shell during install (a supply-chain
  smuggling vector).
- `scripts.install`: same reason. Vendor dependencies into the bundle instead.
- `runtime.base_image`: would let a bundle pull an arbitrary OCI image as its rootfs. Bundles
  use the engine-allowlisted base image instead.

Required fields:

- `name`: must equal the install target (the value passed to `iii worker add`).
- `scripts.start`: a non-empty shell string. The engine `exec`s this inside the sandbox VM.
  Example: `node bundle.js`, `python -m worker`, `bun run bundle.js`.

Optional fields (clamped against engine caps, with a `W182 BundleResourceClamped` warning when
the request exceeds the cap):

- `resources.cpus`: defaults to `2`, clamped to `4`.
- `resources.memory`: defaults to `2048` MiB, clamped to `4096` MiB.

```yaml
name: my-worker
version: 1.2.0
scripts:
  start: node bundle.js
resources:
  cpus: 2
  memory: 2048
```

### Archive safety policy

Bundle archives are extracted with tighter limits than OCI layers:

| Limit                       | Value              |
|-----------------------------|--------------------|
| Total uncompressed size     | 64 MiB             |
| Largest single file         | 32 MiB             |
| Maximum entry count         | 1024               |
| Maximum directory depth     | 16                 |
| Allowed tar entry types     | Regular, Directory |

Archives containing symlinks, hard links, character devices, FIFOs, or paths with `..`
components are rejected with `W181 BundleArchiveUnsafe`.

### Error codes

| Code   | Failure                                                                                            |
|--------|----------------------------------------------------------------------------------------------------|
| `W142` | Archive download failed (HTTP error, unexpected content-type, size cap, sha256 mismatch).          |
| `W180` | Manifest rejected (forbidden field like `scripts.setup` or `runtime.base_image`).                  |
| `W181` | Archive contains unsafe entries (symlink, hardlink, traversal, oversized, too many entries).       |
| `W182` | Resource request exceeded engine cap; install proceeded with clamped values (warn, not fail).      |
| `W183` | Dependency graph too wide or too deep (max depth 5, max transitive count 32).                      |

{/* TODO: document the publish flow (`iii worker publish bundle.tar.gz`?), the registry's
storage layout, and the recommended bundler configurations for Node/Bun/Python. */}

Files in this skill

  • functions.mdx6.1 KB
  • functions.mdx.skill.md6.1 KB
  • triggers.mdx6.7 KB
  • triggers.mdx.skill.md6.7 KB
  • workers-registry.mdx6.1 KB
  • workers-registry.mdx.skill.md6.1 KB
  • workers.mdx5.6 KB
  • workers.mdx.skill.md5.6 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…